본문 바로가기

Spring Boot

[SpringBoot] @Mock vs @MockBean

 

📌 어떤 객체를 Mock 객체로 선언하는 방법


1️⃣ mock()
PostRepository postRepository = mock(PostRepository.class);

2️⃣ @Mock
@Mock
private PostRepository postRespository;
+ @Mock을 쓰려면 테스트 클래스 위에 @ExtendWith(MockitoExtension.class)를 붙여줘야 함

①과 ②는 내부적으로 동일하게 동작함. 무엇을 쓰는지는 방법의 차이

3️⃣ @MockBean
@MockBean
private PostRepository postRespository;
스프링 부트 테스트에서 제공하는 어노테이션
스프링 컨텍스트에 Mock 객체를 등록하고,
스프링 컨텍스트에 의해 @Autowired가 동작할 때 등록된 mock객체를 사용할 수 있도록 동작함

📌 @InjectMocks


해당 클래스의 Mock 객체들을 감지하고,
해당 클래스의 객체를 만들 때 필요한 의존성에 맞는 Mock 객체를 주입

    @Mock  
    private AccountRepository accountRepository;  

    @InjectMocks  
    private AccountService accountService;  
    // => AccountService 객체를 만들 때 필요한 의존성을 감지하고, 해당하는 목객체인 accountRepository를 주입

📌 @Mock vs. @MockBean


  @Mock @MockBean
대상 테스트 단위 테스트 스프링 컨테이너가 필요한 테스트
의존성 주입 @InjectMocks @Autowired
관례적 쓰임 서비스 테스트에서 레포지토리를 모킹 컨트롤러 테스트에서 서비스를 모킹

스프링 컨테이너에 빈을 등록해야하는 테스트에서는 MockBean을,
단위 테스트를 할 때에는 Mock을 사용한다.
@MockBean으로 만든 mock 객체를 주입받고 싶을 때는 @Autowired를
@Mock으로 만든 mock 객체를 주입받고 싶을 때는 @InjectMocks를 사용한다.
관례적으로 서비스 테스트에서 레포지토리를 모킹해올때 @Mock 을
빈 주입을 요구하는 컨트롤러 테스트에서는 @MockBean을 사용한다.
※ MockBean으로 스프링 컨텍스트에 빈으로 등록한 mock 객체는 InjectMocks에 의해 주입될 수 없다! => 에러 발생함

📌 컨트롤러 테스트


WebMvcTest는 스프링 컨테이너에 빈을 등록하여 테스트하므로 @MockBean을 사용해야 함

@WebMvcTest(AccountController.class)  
class AccountControllerTest {  
    // mock 객체를 스프링 컨테이너에 등록  
    @MockBean  
    private AccountService accountService;  

    @Autowired  
    private MockMvc mockMvc;  

    @Autowired  
    private ObjectMapper objectMapper;  

 (중략)  
}  

 

📌 서비스 테스트


서비스 테스트는 스프링 컨테이너 없이 단위테스트가 가능하므로 @Mock을 사용해야 함

@ExtendWith(MockitoExtension.class)  
public class FarmingHolidayServiceTest {  
    @InjectMocks  
    private FarmingHolidayService sut;  

    @Mock  
    private FarmingHolidayRepository farmingHolidayRepository;  

(중략)  
}