본문 바로가기
Backend/Spring Boot

@WebMvcTest 란?, 가짜로 등록한다는 것의 의미?

by 성장하고픈개발자 2023. 7. 26.
728x90
728x90

컨트롤러 단위테스트를 작성하면서 @WebMvcTest를 사용했다.

시간이 지나면 금방 까먹을 거 같아서 일단 간단히 정리하기...

https://www.appsdeveloperblog.com/the-first-principle-in-unit-testing/

 

The F.I.R.S.T. Principle in Unit Testing - Apps Developer Blog

When writing unit tests, developers try to follow the F.I.R.S.T principle as much as possible. F.I.R.S.T is a combination of multiple principles. Let’s learn

www.appsdeveloperblog.com

참고로 Fast, Independent, Repeatable ,Self-validating, Thorough 이 5가지가 단위 테스팅 principle 이라고 한다.

 

@WebMvcTest 는 스프링 부트에서 제공하는 어노테이션 중 하나로, 웹 애플리케이션의 MVC 컨트 롤러(Controller)를 테스트하기 위해 사용됩니다. @WebMvcTest 어노테이션은 특정 컨트롤러를 대상으로 하는 단위 테스트를 작성할 때 사용됩니다. 이 어노테이션을 사용하면 웹 레이어에서 발생하는 요청과 응답을 테스트할 수 있습니다. 

 

원하는 컨트롤러를 등록하여 직접 메모리에 올려줘야 하고 시큐리티 파일도 내가 만든 것 이기 때문에 직접 import 해줘야 한다.

 

@Import({
        FakeStore.class, //s->r->db 대용 더미데이터들
        SecurityConfig.class
})
@WebMvcTest(controllers = {CartRestController.class})
//특정 컨트롤러를 IoC 컨테이너에 등록한다.

컨트롤러 단위 테스트를 할 때는 무엇을 가짜로 띄울지 결정할 수 있어야 하는 것이 중요하다.


추가로, DI에 대해 간단한 예시를 들자면,

Animal(부모) Dog (자식)이라고 하자. Dog를 컴포넌트 스캔해서 DI를 할 때,

@Autowired
Animal a;

이라고 하면 IoC 에서 찾아낼 때 IoC에서 Animal 타입을 스캔해서 찾아내는데 Dog가 Animal 타입 이므로 Dog도 DI 해준다.


가짜로 띄운다는 의미는??

package org.springframework.boot.test.mock.mockito; 이 패키지 안에 있는

@MockBean 어노테이션을 이용해서 가짜 객체로 등록한다. 

 

이렇게 UserService를 가짜 객체로 등록했을 때 이런식으로 껍데기(추상클래스)만 있는 상태가 된다. 사진은 그저 예시...


그렇다면, 지금 현재 나의 코드 상황으로는 UserRestController 가 UserService 를 의존성주입 받고 있고 GlobalExceptionHandler (AOP 적용 전) 를 의존성 주입 받고 있는 상황이다.

또 내가 만든 GlobalExceptionHandler 클래스는 ErrorLogRepository 클래스를 의존하고 있는데, 지금 내가 테스트를 해보고 싶은 상황을 생각해보면...!!

 

GlobalExceptionHandler는 로그를 확인하고 싶기 때문에 테스트 하고 싶고, ErrorLogRepository는 테스트 하기 싫고 UserService 또한 그냥 컨트롤러 테스트만 할 거기 때문에 테스트 해보기 싫다.

 

따라서 이렇게 코드를 작성해 볼 수 있다.

@Import({
        SecurityConfig.class,
        GlobalExceptionHandler.class
})
@WebMvcTest(controllers = {CartRestController.class})
public class UserRestControllerTest {

    // 객체의 모든 메서드는 추상메서드로 구현됩니다. (가짜로 만들면)
    // 해당 객체는 SpringContext에 등록됩니다.
    @MockBean
    private UserService userService;

    @MockBean
    private ErrorLogJPARepository errorLogJPARepository;

    // @WebMvcTest를 하면 MockMvc가 SpringContext에 등록되기 때문에 DI할 수 있다.
    @Autowired
    private MockMvc mvc;

    // @WebMvcTest를 하면 ObjectMapper가 SpringContext에 등록되기 때문에 DI할 수 있다.
    @Autowired
    private ObjectMapper om;

위 코드처럼 @Import 안에 있는 두 클래스는 "진짜" 객체로 등록한 걸 볼 수 있고

테스트 하고싶지 않은 두 클래스는 @MockBean으로 등록한 걸 볼 수 있다.

ObjectMapper은 테스트 결과를 직렬화된 값으로 확인하기 위해서 사용하였다.

 

다음에 테스팅 하는 방법을 자세히 설명하겠다.

728x90
728x90