입력하다
컨트롤러를 테스트하기 위해 코드를 열심히 작성했습니다.
제 기억력에 의지해서 썼는데… 실패했을 뿐만 아니라 컨텍스트로더도 전혀 작동하지 않아서 몇 시간 동안 해결책을 찾다가 해결했습니다. 소요된 시간에 비해 무의미한 양의 문제 해결이었지만 테스트 주석을 배울 수 있는 기회였습니다.
직감과 직감으로 작성된 거친 테스트 코드
잘못된 테스트 코드
@WebMvcTest
@Import( {TestSecurityConfig.class, TestJpaConfig.class} )
@ExtendWith(SpringExtension.class)
@AutoConfigureRestDocs
public class FeedbackControllerTest {
@Autowired
MockMvc mockMvc;
@Autowired
ObjectMapper objectMapper;
@InjectMocks
FeedbackController feedbackController;
@Mock
FeedbackServiceImpl feedbackService;
@Test
@DisplayName(" 요청 인입 시 정상적으로 리턴한다 ")
void writeFeedback_suc() throws Exception {
//... 이하 생략
}

사람이 대충 코드를 작성하면 이런 욕먹을텐데…공식 문서를 읽어보자
불친절하고 읽을 수 없습니다 …
적어도 밑줄 친 부분만 해석한다면 웹 레이어를 테스트하는 데 필요한 컨트롤러와 변환기만 제공하는 간단한 테스트 주석입니다.그러고 보니 그렇네요.. SpringSecurity 및 MockMvc 설정도 자동입니다.한다고 한다
@MockBean, @Import와 같이 쓰라고 되어있는데 @Mock으로 2시간째 놀고 있습니다.
변경된 코드
@WebMvcTest( FeedbackController.class )
@Import( TestSecurityConfig.class )
@ExtendWith(SpringExtension.class)
@AutoConfigureRestDocs
public class FeedbackControllerTest {
@Autowired
MockMvc mockMvc;
@Autowired
ObjectMapper objectMapper;
@MockBean
FeedbackServiceImpl feedbackService;
@MockBean
ModelMapper modelMapper;
@Test
@DisplayName(" 요청 인입 시 정상적으로 리턴한다 ")
void writeFeedback_suc() throws Exception {
//test code
}
}
변경된 사항
1. @InjectMocks 삭제
FeedbackController는 WebMvcTest에 이미 테스트 대상이라고 알려줬기 때문에 삭제할 수 있습니다.
2. @Mock 대신 @MockBean
공식 문서에 명시된 바와 같이 MockBean은 종속 클래스를 Bean으로 대체하는 데 사용되었습니다.
그렇다면 @ExtendWith 및 @InjectMocks와 같은 나머지 주석을 정리하겠습니다.
@ExtendWith(SpringExtension.class)
스프링 기능은 JUnit 테스트에서도 사용할 수 있습니다.
package org.springframework.test.context.junit.jupiter;
그래서 JUnit에서 제공하는 클래스입니다.

참고로 내부에 이런 메소드가 있습니다.

@Autowired가 내부적으로 사용되는지 확인하고(메서드에는 @Autowired가 추가되지 않아야 함) 이중 확인을 피하기 위해 캐시하는 기능입니다.
@InjectMocks
Mockito 프레임워크의 주석오전.
예를 들어 제품 서비스가 제품 리포지토리에 의존하는 경우
@InjectMocks ProductService productService;
@Mock ProductRepository productRepository;
이렇게 쓸 수 있습니다
WebMvsTest와 Mock을 함께 사용할 수 없는 이유는 무엇입니까?
기본적으로 WebMvcTest는 Spring Framework에 속합니다. 그래서 콩을 사용
반면에, Mockito는 Spring 애플리케이션 컨텍스트와 독립적입니다. 그래서 콩을로드하지 마십시오
즉, WebMvcTest에서는 @Mock을 사용할 수 있는 경우가 없고 @Mock을 추가하더라도 SpringContext에 없기 때문에 사용할 수 없다.
그래서 Mock 객체를 생성하고자 한다면 @MockBean을 작성하여 @WebMvcTest에 빈으로 등록할 수 있도록 해야 한다.
나가
요약하자면,
1. 컨트롤러 테스트를 하고자 한다면 통합 테스트가 아닌 이상 @WebMvcTest를 조심하는 것이 좋다.
2. 이때 @WebMvcTest(Target Class.Class) 형식으로 작성한다.
3. 고립된 테스트를 하고 싶다면 @Mock이 아닌 @MockBean을 사용해야 합니다.
3-1 그 이유는 @WebMvcTest 자체가 스프링 컨텍스트에서 일부 웹 레이어 관련 빈을 로드하고 테스트하는 원칙에 따라 작동하기 때문입니다. 즉, WebMvcTest가 인식하기 위해서는 bean으로 등록되어야 합니다.
참조
https://docs.spring.io/spring-framework/docs/current/reference/html/testing.html#testing



