단위 테스트(@Mock)
세 줄 요약
- 현재 개발 중인 코드가 의존하는 코드는 모킹을 통해 처리할 수 있다.
- 목 객체는 그 내용이 없더라도 테스트할 수 있다.
- when과 thenResult를 통해 목 객체의 행동을 정의한다.
단위 테스트와 모킹
통합 테스트는 '현재 개발 중인 코드' 외에도 '현재 개발 중인 코드가 의존하고 있는 코드'까지 대상으로 실행되는 반면,
단위 테스트는 '현재 개발 중인 코드' 만을 타겟으로 테스트할 수 있습니다.
모킹
모킹은 위에서 언급한 것과 같이, 테스트 상황에서 현재 개발 중인 코드가 의존하고 있는 코드를 처리하는 기술입니다.
자바에서는 모킹 라이브러리로 'Mockito'를 많이 사용합니다.
@ExtendWith(MockitoExtension.class)
단위 테스트에 사용되는 어노테이션입니다.
@SpringBootTest와 달리 스프링 부트 어플리케이션을 실행시키지 않고 테스트 코드를 실행할 수 있습니다.
@Mock, @InjectMocks
현재 개발 중인 코드에는 @InjectMocks 어노테이션을, 현재 개발 중인 코드가 의존하는 객체에는 @Mock을 붙여줍니다.
말 그대로 @InjectMocks 어노테이션을 통해 @Mock이 붙은 객체들을 주입받습니다.
모킹된 테스트 코드의 작동원리
소스 코드
(생략)
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
@ExtendWith(MockitoExtension.class) // 스프링 부트 어플리케이션이 실행되지 않는 테스트
class ProductServiceUnitTest {
@Mock // 의존하는 객체의 모킹처리
private ProductRepository productRepository;
@Mock
private ValidationService validationService;
@InjectMocks // 목 객체 주입
private ProductService productService;
@Test
@DisplayName("상품 추가 후에는 추가된 상품이 반환되어야 한다")
void productAddTest() {
ProductDTO productDTO = new ProductDTO("pencil", 200, 10);
Long PRODUCT_ID = 1L;
Product product = ProductDTO.toEntity(productDTO);
product.setId(PRODUCT_ID);
when(productRepository.add(any())).thenReturn(product); // 모킹된 객체의 행동을 정의
ProductDTO savedProductDTO = productService.add(productDTO); // 현재 개발 중인 코드(or 메소드)
assertTrue(savedProductDTO.getId().equals(PRODUCT_ID));
assertTrue(savedProductDTO.getName().equals(productDTO.getName()));
assertTrue(savedProductDTO.getPrice().equals(productDTO.getPrice()));
assertTrue(savedProductDTO.getAmount().equals(productDTO.getAmount()));
}
}
when( ) 메소드와 any( ) 메소드는 assertTrue와 마찬가지로 org.mockito.Mockito.* 패키지를 import static 해서 메소드 이름만으로 사용 가능합니다.
when과 thenReturn으로 구분해서 보면, when에 해당하는 동작을 수행할 때 thenReturn에 있는 값을 반환합니다.
여기서 any()는 아무 값이나 들어가는 것을 의미합니다.
productRepository.add(아무값) → product 반환
이렇게 정의된 목 객체의 행동은 현재 개발 중인 코드(메소드)에서 확인할 수 있습니다.

목 객체 주입 확인
현재 개발 중인 코드(메소드)에서 모킹한 부분에 break point를 걸고 테스트 디버깅을 실시하면 아래와 같이 목 객체임을 확인할 수 있습니다.


이처럼 의존하는 객체의 내용이 없는 상태에서도 개발 중인 코드(메소드)를 테스트해 볼 수 있습니다.