@ExtendWith(MockitoExtension.class)을 활용하여 스프링 컨텍스트를 띄우지 않는 빠른 서비스 단위 테스트가 가능하다.
서비스 테스트 코드는 아래와 같다.
@ExtendWith(MockitoExtension.class)
@DisplayName("SellerProductService 단위 테스트")
class SellerProductServiceTest {
@Mock
private ProductRepository productRepository;
@InjectMocks
private SellerProductService sellerProductService;
@Test
@DisplayName("상품 등록 테스트 : 필수 정보를 포함한 상품 정보 등록 성공 확인")
void registerProduct_Success(){
Long sellerId=24L;
// given
ProductRequestDto requestDto = ProductRequestDto.builder()
.name("겨울 긴팔 티셔츠")
.brandName("테스트 브랜드명")
.info("테스트 인포")
.price(BigDecimal.valueOf(36000))
.image("url")
.colorGroup("밝은")
.tags(List.of("기모", "긴팔T", "겨울", "화이트"))
.stockQuantity(300)
.build();
Product mockProduct = Product.registerProduct(sellerId,requestDto);
// stubbing
given(productRepository.save(any(Product.class))).willReturn(mockProduct);
// when
ProductResponseDto responseDto = sellerProductService.registerProduct(sellerId,requestDto);
// then
assertThat(responseDto).isNotNull();
assertThat(responseDto.getName()).isEqualTo("겨울 긴팔 티셔츠");
assertThat(responseDto.getStockQuantity()).isEqualTo(300);
assertThat(responseDto.getTags())
.isNotNull()
.hasSize(4)
.contains("기모","화이트");
verify(productRepository,times(1)).save(any(Product.class));
}
}
@Mock은 테스트에 필요한 의존성(부품)을 가짜로 만들고 @InjectMocks을 통해 @Mock으로 만든 가짜 부품들을 테스트 대상 객체(Service 등)에 자동으로 주입한다.
ProductRepository는 테스트에는 필요하지만 실제로 사용할 것이 아니기 때문에 실제 로직은 없고 껍데기만 있는 모의 객체로서 만들고 이를 SellerProductService에 주입시켜주는 것이다.
( @WebMvcTest에서 썼던 @MockitoBean은 스프링 컨테이너가 주입해 주는 방식이고 @Mock은 Mockito 라이브러리가 순수 자바 객체 수준에서 주입해 주는 방식이다. )
< 세부 코드 설명 >
컨트롤러 테스트에서는 HTTP 응답 스펙을 효율적으로 검증할 수 있는 MockMvc의 andExpect를 사용했었는데 일반적인 로직 검증이나 복잡한 객체 비교가 필요한 서비스 테스트에서는 AssertJ의 assertThat을 사용한다.
동등성 검증
Null 체크 : 객체나 필드가 초기화되었는지 또는 의도적으로 비어있는 상태인지 검증할 때 사용
컬렉션 크기 및 내용 검증 : List, Set 등 컬렉션 데이터를 검증할 때 필수적
Boolean 검증
예외 검증
.
.
.
다음 포스팅에서는 Repository Layer 테스트하는 방법과 그 예시에 대해 정리한다.