[TIL] 230203

LaStella·2023년 2월 3일
0

유닛테스트 실습

package org.prgms.kdt.order;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.prgms.kdt.voucher.FixedAmountVoucher;
import org.prgms.kdt.voucher.MemoryVoucherRepository;
import org.prgms.kdt.voucher.VoucherService;

import java.util.List;
import java.util.UUID;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.*;

class OrderServiceTest {
    // stub을 만든다면 아래와 같이 만들 수 있습니다.
    class OrderRepositoryStub implements OrderRepository {
        @Override
        public Order insert(Order order) {
            return null;
        }
    }

    @Test
    @DisplayName("오더가 생성되야한다. (stub)")
    void createOrder() {
        // Given
        var voucherRepository = new MemoryVoucherRepository();
        var fixedAmountVoucher = new FixedAmountVoucher(UUID.randomUUID(), 100);
        voucherRepository.insert(fixedAmountVoucher);
        var sut = new OrderService(new VoucherService(voucherRepository), new MemoryOrderRepository());

        // When
        var order = sut.createOrder(UUID.randomUUID(), List.of(new OrderItem(UUID.randomUUID(), 200, 1)), fixedAmountVoucher.getVoucherId());

        // Then
        assertThat(order.totalAmount(), is(100L));
        assertThat(order.getVoucher().isEmpty(), is(false));
        assertThat(order.getVoucher().get().getVoucherId(), is(fixedAmountVoucher.getVoucherId()));
        assertThat(order.getOrderStatus(), is(OrderStatus.ACCEPTED));

    }

    @Test
    @DisplayName("오더가 생성되야한다. (mock)")
    void createOrderByMock() {
        // Given
        var voucherServiceMock = mock(VoucherService.class);
        var orderRepositoryMock = mock(OrderRepository.class);
        var fixedAmountVoucher = new FixedAmountVoucher(UUID.randomUUID(), 100);
        when(voucherServiceMock.getVoucher(fixedAmountVoucher.getVoucherId())).thenReturn(fixedAmountVoucher);
        var sut = new OrderService(voucherServiceMock, orderRepositoryMock);

        // When
        var order = sut.createOrder(
                UUID.randomUUID(),
                List.of(new OrderItem(UUID.randomUUID(), 200, 1)),
                fixedAmountVoucher.getVoucherId());
        // Then
        // 오더에 대한 상태 검증
        assertThat(order.totalAmount(), is(100L));
        assertThat(order.getVoucher().isEmpty(), is(false));
        // 바우처 서비스가 어 행동을 하는지 어떤 메소드가 호출 되는지 검증
        // inOrder를 사용하여 실제 각각의 목들이 어떠한 순서대로 호출이 되는지 까지 검증이 가능합니다.
        var inOrder = inOrder(voucherServiceMock, orderRepositoryMock);
        inOrder.verify(voucherServiceMock).getVoucher(fixedAmountVoucher.getVoucherId());
        inOrder.verify(orderRepositoryMock).insert(order);
        inOrder.verify(voucherServiceMock).useVoucher(fixedAmountVoucher);

    }
}

SpringTest

Testing
스프링 공식문서에서 스프링에서 테스팅 지원을 어떻게 하는지 설명되어있습니다.

단위 테스트 지원

Constructor Based Dependency Injection Pattern(생성자 기반 의존관계 주입)으로 작성한 코드와 같이 컨테이너에서 Autowired를 이용하여 만들필요 없이 Mock객체를 만들어 주입함으로써 테스트를 할 수 있습니다. 따라서 컨테이너 없이 단위 테스트 코드를 작성할 수 있습니다.

  • Mock Objects 지원
  • General Testing Utilities
  • Spring MVC Testing Utilities

통합 테스트 지원

실제 스프링 테스트에서 가장 많이 서포트해주는 부분입니다. 실제 서버를 띄우지 않고 스프링 컨테이너 내에서 각각의 등록된 빈들 간의 연동되어지는 부분들에 테스트가 필요할 때가 많습니다. 이 테스트를 하기 위한 스프링 컨테이너가 필요하며 스프링은 테스트시 IoC 컨테이너를 제공하기 위해서 Spring TestContext Framework를 제공합니다. 테스트 환경에서 ApplicationContext를 애노테이션만으로 쉽게 만들 수 있습니다.

실습

package org.prgms.kdt;


import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.prgms.kdt.order.OrderItem;
import org.prgms.kdt.order.OrderService;
import org.prgms.kdt.order.OrderStatus;
import org.prgms.kdt.voucher.FixedAmountVoucher;
import org.prgms.kdt.voucher.VoucherRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

import java.util.List;
import java.util.UUID;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;

//@ExtendWith(SpringExtension.class)
// ContextConfiguration 은 어떤식으로 applicationContext 가 만들어져야 되는지만 알려줍니다.
// 실질적으로 JUnit 과 상호작용해서 testContext 를 만드는 것은 SpringExtension 을 이용해야합니다.
//@ContextConfiguration

// ExntendsWith, ContextConfiguration을 포함하는 애노테이션
@SpringJUnitConfig
@ActiveProfiles("test")
public class KdtSpringContextTests {

    // ContextConfiguration에 별도로 빈설정을 정의한 클래스나 xml을 전달하지 않으면
    // 현재 클래스내에 Configuration 애노테이션이 달린 클래스를 찾게됩니다.
    @Configuration
    @ComponentScan(
            basePackages = {"org.prgms.kdt.voucher", "org.prgms.kdt.order"}
    )
    static class Config {

    }

    @Autowired
    ApplicationContext context;

    @Autowired
    OrderService orderService;

    @Autowired
    VoucherRepository voucherRepository;

    @Test
    @DisplayName("applicationContext가 생성 되야한다.")
    public void testApplicationContext() {
        assertThat(context, notNullValue());
    }

    @Test
    @DisplayName("VoucherRepository가 빈으로 등록되어 있어야 한다.")
    public void testVoucherRepositoryCreation() {
        var bean = context.getBean(VoucherRepository.class);
        assertThat(bean, notNullValue());
    }

    @Test
    @DisplayName("orderService를 사용해서 주문을 생성할 수 있다.")
    public void testOrderService() {
        // Given
        var fixedAmountVoucher = new FixedAmountVoucher(UUID.randomUUID(), 100);
        voucherRepository.insert(fixedAmountVoucher);

        // When
        var order = orderService.createOrder(
                UUID.randomUUID(),
                List.of(new OrderItem(UUID.randomUUID(), 200, 1)),
                fixedAmountVoucher.getVoucherId());

        // Then
        assertThat(order.totalAmount(), is(100L));
        assertThat(order.getVoucher().isEmpty(), is(false));
        assertThat(order.getVoucher().get().getVoucherId(), is(fixedAmountVoucher.getVoucherId()));
        assertThat(order.getOrderStatus(), is(OrderStatus.ACCEPTED));
    }

}
profile
개발자가 되어가는 중...

0개의 댓글