barded

[무물] 2-3. 계층별 단위테스트 - Controller 본문

프로젝트/무물

[무물] 2-3. 계층별 단위테스트 - Controller

barded 2024. 6. 6. 14:42

Controller 계층의 단위 테스트 역할

Controller 계층의 단위 테스트는 Service를 MockBean객체로 주입받은 후, 호출하여 예상한 결과가 맞는지 확인하면 된다.

FromMeControllerTest

@ActiveProfiles("local")
@WebMvcTest(FromMeController.class)
@MockBean(JpaMetamodelMappingContext.class)
class FromMeControllerTest {

    final String USERNAME = "USERNAME";

    @Autowired
    MockMvc mockMvc;

    @MockBean
    FromMeService fromMeService;

    @MockBean
    UserDetailService userDetailService;

    @BeforeEach
    void setUp() {
        mockMvc = MockMvcBuilders.standaloneSetup(new FromMeController(fromMeService))
            .setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver()).build();
    }

    @Test
    @DisplayName("FromMe 피드")
    public void getFromMeFeed() throws Exception {

        //given
        List<PostResponseDto> postResponseDtos = List.of(
            new PostResponseDto(1L, "test", "test", null, 1L, null, 0L, null, 0L, false, LocalDateTime.now()),
            new PostResponseDto(2L, "test", "test", null, 1L, null, 0L, null, 0L, false, LocalDateTime.now())
        );
        
        User user = new User("test", "test", null);
        given(userDetailService.getUser(1L)).willReturn(new UserDetailDto(1L, USERNAME));
        given(fromMeService.getFromMeFeed(any(UserDetailDto.class), any(String.class), any(Pageable.class))).willReturn(postResponseDtos);

        //when
        ResultActions actions = mockMvc.perform(get("/fromme")
            .param("username", USERNAME)
            .param("pageNumber", "0")
            .param("pageSize", "10")
            .with(SecurityMockMvcRequestPostProcessors.user(user))  // 모의 인증된 사용자 주입
            .accept(MediaType.APPLICATION_JSON)
            .contentType(MediaType.APPLICATION_JSON))
            .andDo(print());

        //then
        actions.andExpect(status().isOk())
            .andExpect(jsonPath("$[0].id").value(1L));
        
    }

}

Controller 계층의 Annotation들

  • @ActiveProfiles("local"):
    • 테스트가 실행될 때 "local" 프로필을 활성화함으로써, 개발 환경에 특화된 설정을 적용함.
  • @WebMvcTest(FromMeController.class):
    • Spring MVC에 집중할 수 있는 테스트 환경을 제공함. 여기서는 FromMeController에 대한 웹 계층만을 테스트하기 위해 사용됨.
  • @MockBean(JpaMetamodelMappingContext.class):
    • JPA 메타모델을 위한 목(Mock) 객체를 생성함으로써, 실제 데이터베이스를 사용하지 않고 테스트를 진행할 수 있게 함.
  • @Autowired:
    • Spring의 의존성 주입 기능을 사용하여 MockMvc 인스턴스를 자동으로 주입함.
  • @MockBean:
    • 테스트에서 사용될 서비스(FromMeService, UserDetailService)의 목(Mock) 객체를 생성함. 이를 통해 실제 서비스 로직을 실행하지 않고도 서비스의 행동을 모의할 수 있게 함.
  • @BeforeEach:
    • 각 테스트가 실행되기 전에 공통적으로 수행해야 할 작업을 정의함. 여기서는 MockMvc 인스턴스를 설정함.
  • @Test:
    • 실제 테스트를 수행하는 메서드임을 나타냄.
  • @DisplayName("FromMe 피드"):
    • 테스트 결과 보고서에서 보여질 테스트의 이름을 "FromMe 피드"로 지정함.

Controller의 Given-When-Then

  • given:
    • 테스트를 실행하기 전에 필요한 사전 조건을 설정함. 이 경우에는 특정 사용자의 정보와 "FromMe 피드"를 가져오기 위해 필요한 가짜(PostResponseDto 리스트) 응답을 준비함. 또한, userDetailService.getUser(1L)와 fromMeService.getFromMeFeed 메서드가 호출될 때 반환할 값을 지정함으로써, 실제 서비스 로직을 실행하지 않고도 테스트가 가능하게 함.
  • when:
    • 실제로 테스트하고자 하는 행동을 실행함. 여기서는 "/fromme" 엔드포인트에 HTTP GET 요청을 보내는 것이며, 이 요청에는 사용자 이름, 페이지 번호, 페이지 크기를 파라미터로 포함함. 또한, SecurityMockMvcRequestPostProcessors.user(user)를 사용해 모의 인증된 사용자 정보를 요청에 주입함.
  • then:
    • when 단계에서 실행한 행동의 결과를 검증함. 여기서는 응답 상태 코드가 200(OK)인지 확인하고, JSON 응답 본문의 첫 번째 항목의 id가 1L(기대하는 값)인지 확인함으로써, API가 올바르게 작동하는지 검증함.

setUp() 메서드 설명

@BeforeEach로 표시된 setUp 메서드는 각 테스트가 실행되기 전에 자동으로 실행됨. 이 메서드에서는 MockMvc 인스턴스를 초기화하는 작업을 수행함. 구체적으로, FromMeController의 인스턴스를 생성하고, 이를 사용하여 MockMvcBuilders를 통해 MockMvc 인스턴스를 설정함. 여기서 fromMeService를 FromMeController의 생성자에 주입하여, 실제 서비스 로직을 모의로 대체할 수 있게 함.

또한, setCustomArgumentResolvers 메서드를 통해 PageableHandlerMethodArgumentResolver를 커스텀 인자 해석기로 설정함. 이는 Spring MVC에서 페이지네이션과 관련된 파라미터를 처리할 수 있게 해줌. 마지막으로, build() 메서드를 호출하여 설정을 마치고 MockMvc 인스턴스를 생성함. 이렇게 설정된 MockMvc 인스턴스는 테스트 중에 컨트롤러의 요청을 모의로 처리하는데 사용됨.

 

[무물] 1. 단위테스트 / 통합 테스트 란?

[무물] 2-1.계층별 단위테스트 - Repository

[무물] 2-2. 계층별 단위테스트 - Service

[무물] 2-3. 계층별 단위테스트 - Controller

[무물] 3-1. 통합테스트  MockMvc vs. WebTestClient vs. TestRestTemplate

[무물] 3-2. 통합테스트

[무물] 4. 단위 테스트 네이밍 컨벤션