일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- springboot
- DATABASE
- JS
- EXTJS
- 개발공부
- restapi
- GIT
- 자바
- 보안취약점
- 자바스크립트
- Vue
- 컴포넌트
- 데이터베이스
- 스프링부트
- 리액트
- React
- 개발
- sql
- table
- Spring
- jdk
- 스프링
- javascript
- java
- mssql
- component
- 쿼리
- crud
- reactjs
- Intellij
- Today
- Total
준준의 기록일지
[스프링 에러]Controller Test 시 Repository bean 생성 문제 본문
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
spring boot Run을 하면 빈 주입부터 실행까지 잘 되는데, Controller Test만 하면 Repository를 불러오지 못하는 문제가 발생했다.
기초가 부족해서 Junit4에서 Junit5로도 바꿔보고, 프로젝트도 다시 생성해보고, 별 쇼를 다했고, 빈을 다시 생성해보고 등등 뭐 많이 해봤는데, 문제는 단 ㅎ.....한 줄이였다.
먼저 에러코드는 다음과 같다. Junit 에서는 Failed to load ApplicationContext 에러를 뱉었다.
에러 console
*************************** APPLICATION FAILED TO START *************************** Description: Field repository in com.example.demo.interfaces.RestaurantController required a bean of type 'com.example.demo.domain.RestaurantRepository' that could not be found. The injection point has the following annotations: - @org.springframework.beans.factory.annotation.Autowired(required=true) Action: Consider defining a bean of type 'com.example.demo.domain.RestaurantRepository' in your configuration. 2020-07-29 15:21:08.948 ERROR 34172 --- [ main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@366ac49b] to prepare test instance [com.example.demo.interfaces.RestaurantControllerTest@24d09c1] java.lang.IllegalStateException: Failed to load ApplicationContext
/*
* 실제로 컨트롤러 webmvctest를 할때 제대로된 저장소를 사용할 수 없다.
* 그래서 이댸 직접 컨트롤러에 의존성 주입을 해줘야 한다. %like% @SpyBean
*/
해결방법 = @SpyBean
해당 어노테이션을이용해 Repository 코드를 체크하고 단위 테스트를 진행할 수 있다.
실제 컨트롤러 WebMvcTest를 하면 제대로된 저장소를 사용할 수 없다.
그래서 이때 직접 컨트롤러에 의존성 주입을 해줘야한다. -> 이때 사용하는 것이 @SpyBean
==================================================
@SpyBean
private RestaurantRepository restaurantRepository;
==================================================
이렇게 하면 Repsitory를 정상적으로 불러와서 테스트를 진행할 수 있다.
만약 여기서 Repository를 구현체와 인터페이스로 구분할 경우 restaurantRepository 실질적인 구현이 없는 인터페이스기 때문에 오류가 발생한다.
-> 이때 아래와 같이 구현체를 명시해주면 오류가 해결된다.
@SpyBean(RestaurantRepositoryImpl.class)
private RestaurantRepository restaurantRepository;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package com.example.demo.interfaces;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import com.example.demo.domain.RestaurantRepository;
import static org.hamcrest.CoreMatchers.containsString;
@RunWith(SpringRunner.class)
@WebMvcTest(RestaurantController.class)
public class RestaurantControllerTest {
@Autowired
private MockMvc mvc;
/*
* 실제로 컨트롤러 webmvctest를 할때 제대로된 저장소를 사용할 수 없다.
* 그래서 이댸 직접 컨트롤러에 의존성 주입을 해줘야 한다. %like% @SpyBean
*/
@SpyBean
private RestaurantRepository restaurantRepository;
@Test
public void list() throws Exception {
mvc.perform(get("/restaurants"))
.andExpect(status().isOk())
.andExpect(content().string(
containsString("\"name\":\"bob zip\"")
))
.andExpect(content().string(
containsString("\"id\":1004")
));
}
}
|
cs |
참고사항
Spring Boot 1.4부터 @MockBean과 @SpyBean이 추가됬다.
- @MockBean은 껍데기만 그 객체의 형태를 유지하고, 내부 구현은 사용자가 when, given이나 기타 등등을 통해서 사용자가 직접 정의해줘야한다.
- @SpyBean을 사용하면 given, when을 한것 외에 실제 객체를 사용한다.