나는 지금 새로운 프로젝트를 진행중이다.
@WebMvcTest(MyMovieController.class)
class MyMovieControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private MyMovieService myMovieService;
@Test
void getMovieListNoContentTest() throws Exception {
// given
Long pageNum = 10L;
// when
List<MovieResponseDto> movieList = new ArrayList<>();
when(myMovieService.getMoviesPaging(pageNum)).thenReturn(movieList);
// then
mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/movies/pages/{pageNum}", pageNum)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isNoContent())
.andReturn();
verify(myMovieService, times(1)).getMoviesPaging(pageNum);
}
}
Application Context에서 "모든" 컴포넌트를 스캔하는 것이 아니라,
@WebMvcTest(Target.class)
위와 같이 목표로하는 클래스만 스캔하도록 해주는 어노테이션이다.
@SpringBootTest 어노테이션은 전체 컴포넌트를 스캔하므로 성능상 유리하다.
Target 클래스가 주입받아야 할 객체는 @MockBean 어노테이션을 사용해서 의존 주입 받는다(가짜 객체 형태로)
Service, Repository dependency가 필요한 경우에는 @MockBean으로 주입받아 테스트를 진행 한다.
mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/movies/pages/{pageNum}", pageNum)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isNoContent())
.andReturn();
위 문서에서 해당 클래스의 매서드들을 더 자세히 알 수 있다.
요청의 헤더에 존재하는 Content-Type 을 String 값으로 설정한다.
위에서는 JSON
RequestMatcher? ResultMatcher ?
위와 같이 이전에 했던대로 @WebMvcTest() 어노테이션을 통해 타겟을 정하고 테스트 하려는데, 문제가 생겼다.
위와 같은 형태로 인증 객체를 불러오는 과정(UserDetailsImpl 의 getUser() 매서드)에서, user가 null이 들어갔던 것.
그렇다면, MockBean 으로 UserDetails 를 의존주입해서 사용한다면?
마찬가지로 예외가 발생한다.
@BeforeEach
void setUp(){
user = mock(User.class); // user 목 객체 생성
when(user.getId()).thenReturn(1L); // 유저의 아이디는 1로
userDetails = mock(UserDetailsImpl.class);
when(userDetails.getUser()).thenReturn(user); // userDetailsImpl 에서 getUSER() 호출 시 위 유저 반환하도록 설정
SecurityContext context = SecurityContextHolder.getContext();
context.setAuthentication(new UsernamePasswordAuthenticationToken(userDetails, null, null));
}
위와 같이, SecurityContext 에서 Authentication 을 명시적으로 설정 해 주면 필터를 잘 타면서 테스트가 완료된다.