오늘은 테스트에 이어 mock을 공부해보았다.
이상적으로 각 테스트 케이스는 서로 분리되어야 하지만 현실적으로 프로젝트 상에서 객체들이 이미 얽혀 있기 때문에(의존성) 이러한 상황에서 테스트를 하기 위해 Mock객체(가짜 객체)를 사용한다.
Mock 객체를 편하게 만들고 관리해주는 라이브러리
Spring Boot 2.2+ 사용시 spring-boot-start-test에서 자동으로 Mokito를 추가해준다.
그 이전 버전 사용시 build.gradle의 dependencies에 아래 코드 삽입
testImplementation 'org.mockito:mockito-core:4.8.0'
testImplementation 'org.mockito:mockito-junit-jupiter:4.8.0'
@ExtendWith(MockitoExtension.class)
class ProductServiceTest {
@Mock // (1)
ProductRepository productRepository;
@InjectMocks // (2)
ProductService productService;
@Mock
User user;
@Test
@DisplayName("관심 상품 희망가 - 최저가 이상으로 변경")
void updateProduct_Success() {
// given 부분
Long userId = 777L;
Product product = new Product(requestProductDto, userId);
// 생략...
// when 부분
// user.getId()를 실행하면 given에서 설정한 userId를 반환
when(user.getId())
.thenReturn(userId);
// repo에서 .findBy~를 실행하면 given에서 설정한 product를 반환
when(productRepository.findByIdAndUserId(productId, userId))
.thenReturn(Optional.of(product));
// when, then
assertDoesNotThrow( () -> {
productService.updateProduct(productId, requestMyPriceDto, user);
});
}
(1) : @Mock으로 모킹할 객체 표기. 필요한 객체들을 모킹
(2) : @InjectMocks로 모킹한 객체 주입. @InjectMocks이 붙은 서비스에는 @Mock이 붙은 가짜 repository와 User가 주입된다.
(3) : When() 메서드로 모킹한 객체들이 특정조건으로 특정 메서드를 호출하면 다음과 같이 동작하도록 지정해준다.