작업한 로직을 테스트하기 위해 컨트롤러에 단위 테스트 클래스를 작성하고, @WebMvcTest로 URL에 요청 테스트를 시도해 봤습니다. 하지만 예상보다 많은 난관이 있어 처음에는 쉽게 진행되지 않았습니다. 특히 여러 서비스와 유틸리티 클래스들을 어떻게 처리할지에 대해 고민이 많았네요. 🥲
No qualifying bean of type available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
위와 같은 에러가 발생하면서 테스트가 중단되었고, 이에 대한 해결책을 찾아야 했습니다. 😂 이 에러는 기본적으로 Spring이 주입할 수 있는 빈을 찾지 못했다는 의미입니다. @WebMvcTest는 기본적으로 컨트롤러만 로드하고, 다른 서비스나 유틸리티 클래스 같은 빈들은 로드하지 않기 때문에 발생합니다. 예를 들어, 컨트롤러 내에서 사용하는 서비스가 @Autowired로 주입되어 있을 경우, 해당 서비스가 모킹 되지 않으면 이와 같은 에러가 발생할 수 있습니다.
@WebMvcTest는 컨트롤러와 관련된 빈만 로드합니다. 즉, 서비스나 유틸리티 클래스 같은 다른 빈들은 로드되지 않기 때문에, 테스트에서 실제로 필요한 빈을 @MockBean으로 추가해야 합니다.
@WebMvcTest
public class ControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private TestService testService;
@Test
public void test_success() throws Exception {
// Mocking testService response
when(testService.getList(any(Request.class))).thenReturn(new TestResponse());
mockMvc.perform(get("/api/v1/getList")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andDo(print());
}
}
위와 같이 필요한 빈만 @MockBean으로 주입하고, 나머지 빈은 실제 빈으로 테스트를 수행할 수 있습니다. 이렇게 하면 테스트 범위가 좁아지고, 관리가 용이합니다.
하지만, 주입해야 할 빈이 50개를 넘을 경우에는 각 빈을 하나하나 @MockBean으로 추가하는 것이 매우 비효율적이고, 테스트가 복잡해집니다. 이런 상황에서 더 나은 방법을 찾아야겠죠? 🤔
@SpringBootTest 활용하기
애플리케이션 전체를 테스트하려면, @SpringBootTest를 사용하는 방법이 있습니다. @SpringBootTest는 애플리케이션 컨텍스트 전체를 로드하며, @AutoConfigureMockMvc로 MockMvc를 자동으로 설정해 줍니다. 이 방법을 사용하면, 모든 빈이 로드되며 실제 빈들을 사용하면서 테스트를 진행할 수 있습니다.
@SpringBootTest
@AutoConfigureMockMvc
public class ControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private TestService testService;
@Test
public void test_success() throws Exception {
// Mock the service response
when(testService.getList(any(Request.class))).thenReturn(new TestResponse());
// Perform the request and verify the response
mockMvc.perform(get("/api/v1/getList")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andDo(print());
}
}
@SpringBootTest는 애플리케이션 컨텍스트 전체를 로드하므로, 실제 서비스 빈을 사용하여 테스트할 수 있습니다. 이를 통해 실제 동작 환경을 구현할 수 있으며, @MockBean을 사용하지 않고 모든 빈을 테스트할 수 있습니다.
정리하자면, 빈이 많을 땐 @SpringBootTest와 @AutoConfigureMockMvc로 전체 애플리케이션을 로드하고, 빈이 적을 땐 @WebMvcTest와 @MockBean으로 필요한 빈만 모킹 하여 효율적인 테스트를 할 수 있습니다. 😊
'Framework > Spring' 카테고리의 다른 글
[Spring] Spring에서 요청 받는 법: @ModelAttribute vs @RequestParam - 컴도리돌이 (1) | 2024.11.15 |
---|---|
[Spring] 단위 테스트에서 @WithUserDetails 사용하기: 발생한 에러와 해결 방법 - 컴도리돌이 (4) | 2024.11.13 |
[Spring] 로그인 필요한 API 단위 테스트 - 컴도리돌이 (2) | 2024.11.12 |
[Spring] @Cacheable에서 발생하는 self-invocation 문제 - 컴도리돌이 (2) | 2024.11.05 |
[Spring] @Caching을 활용한 유연한 캐시 관리 - 컴도리돌이 (3) | 2024.11.04 |