테스트 케이스를 작성하다가 좀 헷갈리는게 있었다. @Mock, @MockBean 차이가 뭐지??? 쓰긴 하고 있는데 알고 써야 하지 않을까라는 의문이 들었다. 그래서 찾아봤다.
먼저 Mock 객체를 선언할 때에는 2가지 방법이 있다.
1. 첫번째 : mock() 을 이용해서 선언
1
2
3
4
5
6
7
8
9
10
11
12
|
@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
@InjectMocks
private UserService userService;
UserRepository userRepository = mock(UserRepository.class);
@Test
public void findByEmail_test(){
when(userRepository.findByEmail("test@test.com")).thenReturn(Optional.of(new User()));
userService.findByEmail("test@test.com");
verify(userRepository).findByEmail("test@test.com");
}
}
|
cs |
2. 두번째 : @Mock 을 이용해서 선언
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
@InjectMocks
private UserService userService;
@Mock
private UserRepository userRepository;
@Test
public void findByEmail_test(){
when(userRepository.findByEmail("test@test.com")).thenReturn(Optional.of(new User()));
userService.findByEmail("test@test.com");
verify(userRepository).findByEmail("test@test.com");
}
}
|
cs |
이 2개의 테스트 케이스는 동일하게 동작한다.
그리고 선언한 Mock 객체를 테스트를 실행하는 동안 사용할수 있게 하기 위한 작업이 있다. 바로 위에서 보이는 @RunWith(MockitoJUnitRunner.class) 가 바로 그 역할을 해준다. 또다른 방법으로는 아래와 같은 메소드를 테스트케이스 실행 전에 실행 시키면 된다.
1
2
3
4
|
@Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
|
cs |
여태껏 아무생각없이 둘다 @RunWith랑 initMocks랑 둘다 썼는데 둘다 쓸 필요가 없었다. ㅡㅡ;
그럼 @MockBean 은 뭐지??
@MockBean 은 Mock 과는 달리 org.springframework.boot.test.mock.mockito 패키지 하위에 존재한다. 즉 spring-boot-test에서 제공하는 어노테이션이다. Mockito 의 Mock 객체들을 Spring의 ApplicationContext에 넣어준다. 그리고 동일한 타입의 Bean 이 존재할 경우 MockBean으로 교체해준다.
그럼 언제 @Mock을 쓰고 언제 @MockBean 을 써야 하나??
결론적으로 Spring Boot Container가 필요하고 Bean이 container 에 존재 해야 한다면 @MockBean 을 쓰면 되고 아니라면 @Mock 을 쓰면 된다. 그런데 개인적으로는 그걸 잘 판단을 못하겠다.
1. MockitoJUnitRunner 를 이용해서 Mock을 사용한 Testcase.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
@RunWith(MockitoJUnitRunner.class)
public class RegisterControllerMockTest {
@InjectMocks
private RegisterController registerController;
private ModelAndView model;
@Before
public void setup(){
model = new ModelAndView();
}
@Test
public void showRegistrationPage_test() throws Exception {
registerController.showRegistrationPage(model, new User());
Assert.assertEquals("register", model.getViewName());
}
}
|
cs |
2. SpringRunner와 @WebMvcTest를 사용해서 @MockBean 을 사용한 Testcase
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@RunWith(SpringRunner.class)
@WebMvcTest(value = RegisterController.class, secure = false)
public class RegisterControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@MockBean
private EmailService emailService;
@Test
public void showRegistrationPage_test() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/register"))
.andExpect(status().isOk())
.andExpect(view().name("register"))
.andDo(print());
}
}
|
cs |
분명 이 2개의 테스트 케이스 는 결과는 같지만 실제 내부에서 동작하는 부분은 다르다. 2번만 spring applicaiton context 가 올라간다. 그래서 부득이하게 @MockBean 으로 UserService 와 EmailService를 넣어줘야 했다. 1번은 Controller 객체에 대해서 Mock 을 만들어서 그거에 대해서만 테스트를 한다.(뭐라고 표현을 해야할지 잘 모르겠다.)
이렇게 같은 컨트롤러에 대한 테스트 이지만 작성하기에 따라서 여러가지 방법으로 테스트 케이스를 만들 수 있다. 아직은 미숙하지만 좀더 많이 작성하다 보면 방법도 많이 알게 되고 실제 구현 코드들의 모습도 많이 나아질거라는 생각이 든다.
참고 : https://stackoverflow.com/questions/44200720/difference-between-mock-mockbean-and-mockito-mock
'Development > Java' 카테고리의 다른 글
[SpringBoot] Properties 우선순위 (0) | 2018.06.07 |
---|---|
[SpringSecurity]Spring Reference 수정 (0) | 2018.04.21 |
[SpringBoot]Spring Boot Oauth login With Facebook 삽질기!!! (0) | 2018.03.04 |
작성중-[SpringBoot] ClassPathResource 의 getFile() 사용시 FileNotFoundException 발생 (0) | 2018.01.12 |
[Spring-Data-JPA]Auditing을 추가해보자 (0) | 2017.12.13 |