테스트 코드 빈 등록 에러consider defining a bean of type in your configuration

Sol's·2022년 12월 25일
0

오류

목록 보기
4/18

sns 프로젝트를 만드는 도중 Post기능을 추가하고 PostController와 PostService를 만들기전에 로그인과 회원가입 기능을 테스트 했던 UserTest를 다시 돌려보았다

그런데 PostService를 빈으로 등록 할 수 없다는 오류가 발생했다.

테스트 코드

@WebMvcTest
class UserRestControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Autowired
    ObjectMapper objectMapper;
    
    @MockBean
    UserService userService;

    @Test
    @DisplayName("회원가입 성공")
    @WithMockUser
    void join_success() throws Exception {

        UserJoinRequest userJoinRequest = new UserJoinRequest("id","password");

        mockMvc.perform(post("/api/v1/users/join")
                        .with(csrf())
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsBytes(userJoinRequest)))
                .andDo(print())
                .andExpect(status().isOk())
        ;
    }
}

UserController에는 분명 PostService를 사용하지 않고 있는데 오류가 나서 너무 당황했다.
분명 로컬로 돌렸을때는 Post에 대한 기능들이 전부 잘 돌아갔기때문에 더 당황스러웠다.

그래서 구글검색을 해보았지만...
빈을 등록하는 어노테이션 @Service, @Repository, @Component 등을 잘 사용했는지에대한 이야기 뿐이였다.

그래서 오류가 나는 포인트를 다시 생각해 보았다.
정상적으로 main을 작동할 때는 오류가 나지 않고 Test코드가 작동할 때만 빈등록이 안되었다고 나오니 Test코드 안에서의 문제라고 생각했다.

그래서 @MocBean으로 PostService를 주입하였는데 테스트 코드가 통과하였다!

 @MockBean
    PostService postService;

그런데 의문이 생겼다.
UserController에서는 PostService를 사용하지 않는데 왜 PostService를 빈으로 등록해야 하는걸까??

PostService를 Bean으로 등록해야 하는 이유

원인은 @WebMvcTest에있었다.

@SpringBootTest 어노테이션을 사용하면 스프링이 관리하는 모든 빈을 등록시켜서 통합 테스트를 진행하기 때문에 무겁다.

하지만 @WebMvcTest는 web 레이어 관련 빈들만 등록하므로 비교적 가볍다.
web레이어 관련 빈들만 등록되므로 Service는 등록되지 않는다.
따라서 가짜로 만들어줄 필요가 있다. → @MockBean 활용

@WebMvcTest(Class명.class)
1. ()에 작성된 클래스만 실제로 로드하여 테스트 진행
2. ()에 매개변수를 지정하지 않으면 @Controller, @RestController, @RestControllerAdvice등 컨트롤러와 연관된 Bean이 모드 업로드 된다!!!!

사용이유
스프링의 모든 Bean을 로드하는 @SpringBootTest대신 컨트롤러 관련 코드만 테스트 할 경우 사용된다.

내가 작성한 코드에서는 @WebMvcTest에 매개변수를 주지 않아서였다...
@WebMvcTest에 UserRestController를 넣어주니 오류가 해결된것을 확인 할 수 있었다!!

@WebMvcTest(UserRestController.class)
class UserRestControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Autowired
    ObjectMapper objectMapper;
    
    @MockBean
    UserService userService;

    @Test
    @DisplayName("회원가입 성공")
    @WithMockUser
    void join_success() throws Exception {

        UserJoinRequest userJoinRequest = new UserJoinRequest("id","password");

        mockMvc.perform(post("/api/v1/users/join")
                        .with(csrf())
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsBytes(userJoinRequest)))
                .andDo(print())
                .andExpect(status().isOk())
        ;
    }
}
profile
배우고, 생각하고, 행동해라

0개의 댓글