barded

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

프로젝트/무물

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

barded 2024. 6. 6. 14:44

통합 테스트 역할

Contoller 계층 - Service 계층 - Repository 계층을 한번에 테스트를 진행하는 것이다.

FromMeControllerIntegrationTest

@ActiveProfiles("local")
@Transactional
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class FromMeControllerIntegrationTest {

    final String USERNAME = "USERNAME";

    @Autowired
    WebTestClient webTestClient;

    @MockBean
    FromMeService fromMeService;

    static String accessToken;

    @BeforeEach
    public void setUp() {
        webTestClient.post().uri("/users/signup")
            .contentType(MediaType.APPLICATION_JSON)
            .bodyValue(new SignUpDto("test1", "test1", "test1"))
            .exchange()
            .expectStatus().is2xxSuccessful();

        accessToken = webTestClient.post().uri("/users/login")
            .contentType(MediaType.APPLICATION_JSON)
            .bodyValue(new LoginRequestDto("test", "test"))
            .exchange()
            .expectStatus().isOk()
            .expectBody(LoginResponseDto.class)
            .returnResult()
            .getResponseBody().accessToken();
    }

    @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())
        );
        given(fromMeService.getFromMeFeed(any(UserDetailDto.class), any(String.class), any(Pageable.class))).willReturn(postResponseDtos);

        //when and then
        webTestClient.get().uri(uriBuilder -> uriBuilder.path("/fromme")
            .queryParam("username", USERNAME)
            .queryParam("pageNumber", "0")
            .queryParam("pageSize", "10")
            .build())
						.header("Authorization", "Bearer " + accessToken)
            .exchange()
            .expectStatus().isOk()
            .expectBodyList(PostResponseDto.class)
            .value(response -> {
                assertThat(response).isNotEmpty();
                assertThat(response.size()).isEqualTo(postResponseDtos.size());
                assertThat(response.get(0).options()).isNull();
            });

    }

}

통합테스트의 Annotation들

@ActiveProfiles("local"):

  • 테스트를 수행할 때 "local" 프로필을 활성화함으로써 개발 환경에 특화된 설정을 사용할 수 있게 함. 이는 다양한 환경(개발, 테스트, 운영 등)에 따라 다른 설정을 적용할 수 있도록 함으로써, 테스트가 더 예측 가능하고 일관된 환경에서 실행될 수 있도록 도와준다.

@Transactional:

  • 테스트 클래스에 선언된 경우, 각 테스트 실행 후에 데이터베이스 트랜잭션을 롤백함으로써, 테스트 간의 데이터 격리를 보장함. 이는 테스트가 데이터베이스의 상태에 영향을 주지 않도록 하여 테스트의 독립성을 유지할 수 있게 한다.

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT):

  • 스프링 부트 애플리케이션을 테스트용으로 전체적으로 로드하면서, 임의의 포트에서 웹 환경을 구성함으로써 실제 웹 서버가 구동되는 환경을 모의함. 이는 통합 테스트에서 애플리케이션의 전체 기능을 포괄적으로 테스트할 수 있도록 하며, 실제 HTTP 요청과 응답을 테스트할 수 있게 해준다.

통합 테스트의 Given-When-Then

  • given:
    • 이 부분에서는 테스트를 위한 사전 조건을 설정함. 즉, 테스트 실행 전에 필요한 데이터나 모의 객체의 동작을 정의함. 여기에서는 fromMeService.getFromMeFeed 메소드가 특정 입력에 대해 postResponseDtos 리스트를 반환하도록 모의 설정함. 이 설정은 테스트 실행 중 getFromMeFeed 메소드가 실제 서비스 로직 대신 사전 정의된 응답을 사용하도록 보장함.
  • when:
    • 이 부분에서는 테스트할 실제 동작을 실행함. 즉, 주어진 사전 조건(given) 하에서 특정 이벤트가 발생했을 때 시스템의 반응을 테스트함. 이 코드에서는 /fromme 엔드포인트로 HTTP GET 요청을 보내는 webTestClient를 사용함. 요청에는 username, pageNumber, pageSize 쿼리 파라미터와 Authorization 헤더가 포함됨.
  • then:
    • 이 부분에서는 when에서 실행된 동작의 결과를 검증함. 즉, 시스템이 예상대로 작동하는지 확인함. 여기에서는 응답 상태 코드가 isOk(즉, 200)인지, 응답 본문이 postResponseDtos 리스트와 일치하는지, options 필드가 null인지 검증함. 이는 테스트된 기능이 올바르게 작동하는지를 보장함.

setUp() 메서드 설명

@BeforeEach로 표시된 setUp 메서드는 각 테스트가 실행되기 전에 자동으로 실행됨. 이 메서드에서는 signup 후 login하여 accessToken을 저장한 후 각 테스트코드에 사용되도록 설정함.

 

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

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

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

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

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

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

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