Home Controller 통합 테스트
Post
Cancel

Controller 통합 테스트

스프링 웹 애플리케이션에서 Controller 계층 통합 테스트

Controller 계층의 역할

layered architecture에서 controller 계층은 presentation 계층으로도 불린다.
수신한 client의 요청을 하위 계층인 service 계층에게 위임하는 역할을 한다.

controller 계층에서의 통합 테스트는 실제 Spring Application과 동일한 환경에서의 요청에 대한 응답 결과를 검증한다. 이를 위해서 rest assured를 활용한다.

RestAssured 이란

Java에서 REST API 테스를 쉽게 할 수 있는 도구이다. Java DSL1 형태로 매우 직관적인 형태로 테스트 코드를 작성할 수 있다.
아래 코드의 예시처럼 BDD2스타일 로 요청 및 응답에 대한 검증을 할 수 있다.

1
2
3
4
5
6
7
8
RestAssured
    .given().log().all()
        .contentType(MediaType.APPLICATION_JSON_VALUE)
        .body(PostCreateRequest)
    .when()
        .post("/api/v1/posts")
    .then().log().all()
        .statusCode(HttpStatus.CREATED.value())

RestAssured 설정

build.gradle에 dependencies에 사용할 version만 추가해주면 쉽게 사용할 수 있다.

1
2
3
dependencies {
    testImplementation 'io.rest-assured:rest-assured:5.3.0'
}

Base Class

1
2
3
4
5
6
7
8
9
10
11
12
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class AcceptanceTest {
    @LocalServerPort
    int port;

   @BeforeEach
   public void setUp() {
       if (RestAssured.port == RestAssured.UNDEFINED_PORT) {
           RestAssured.port = port;
       }
   }
}
  • @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    • 임의의 포트번호로 테스트용 SpringBoot 서버를 띄운다.
  • @LocalServerPort
    • RANDOM_PORT로 정해진 포트 번호가 port변수로 주입된다.
  • setUp()
    • SpringBootTest를 RANDOM_PORT로 서버를 띄우기 때문에 restAssured Client가 요청을 보낼 Port를 지정한다.

Controller

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
@RequiredArgsConstructor
public class PostController {

    private final PostSerivce postService;

    @PostMapping("/api/v1/posts")
    public PostResposne createPost(@Valid @RequestBody PostCreateRequest request){
        return postService.createPost(request);
    }

}

enpoint가 /api/v1/posts이고, method가 Post인 createPost에 대한 테스트 코드를 작성해보자.

Test Class Code

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
class PostAcceptanceTest extends AcceptanceTest {

    @DisplayName("게시글 생성 요청시, 게시글을 저장한다.")
    @Test
    void createPost(){
        // given
        PostCreateRequest request = PostCreateRequest.builder()
                .title("테스크 코드 작성법")
                .content("본문 내용")
                .author("sehyeong")
                .build();

        
        // when
        ExtractableResponse<Response> extract =
                given().log().all()
                    .contentType(MediaType.APPLICATION_JSON_VALUE)
                    .body(request)
                .when()
                    .post("/api/v1/posts")
                .then().log().all()
                .extract();

        // then
        assertThat(extract.statusCode()).isEqualTo(HttpStatus.CREATED.value());
        assertThat(extract.header("Location")).isEqualTo("/api/v1/posts/1");
    }
}

mockMvc와 마찬가지로 원하는 endpoint에 요청을 보내고 응답에 대해 검증한다.
mockMvc를 이용한 테스트에서는 하위 레이어가 테스트 더블(가짜 객체)로 구성이 되어있었지만, 이번 테스트 코드는 통합테스트이면서 실제 Apach Tomcat 환경에 대한 요청에 대한 E2E3 성격의 세스트이다.

Refercence

  1. Domain Specific Languages 특정 비지니스 도메인을 위한 특수 프로그래밍 언어 

  2. Behavior-driven development 

  3. End To End Test 

This post is licensed under CC BY 4.0 by the author.

Controller 단위 테스트

테스트 코드의 역할과 필요성