RestAssured를 이용한 테스트 코드 작성하기

JaeYeop·2022년 2월 14일
2

RestAssured 사용 가이드 : https://github.com/rest-assured/rest-assured/wiki/Usage

RestAssured란

REST Assured Java 라이브러리를 사용하여 REST 어플리케이션의 HTTP Endpoint에 초첨을 맞춘 테스트 도구. MockMVC와 같이 테스트를 편리하게 해주는 유용한 테스트 도구이다.

MockMVC와 차이점

MockMvc는 웹 애플리케이션을 애플리케이션 서버에 배포하지 않고도 스프링 MVC의 동작을 재현할 수 있는 라이브러리이며 대부분 Controller Layer Unit Test(단위 테스트)에 사용된다.

실제 서버 환경과 동일한 @SpringBootTest를 사용하지않고 Presentation Layer Bean들만 불러온다. 그리고 그 외 Bean은 Mock 객체 설정을 해주어 순수한 Controller 로직을 테스트한다.

RestAssured의 장점

RestAssured의 장점은 HTTP Endpoint에 초점을 맞춘 테스트 도구인 만큼 컨트롤러단 뿐아니라 서비스단 등 다른 계층의 로직을 한번에 테스트 할 수 있는 장점이 있다.

또한 given / when / then 방식을 채택하여 가독성이 좋아 코드 작성, 분석하기가 편하고 다양한 기능들을 제공하고 있다.

사용법

시작전 - @SpringBootTest를 달고, @beforeEach문에 RestAssured.port를 꼭 지정해주자!

먼저 나 같은 경우는 RestAssured 테스트 코드를 형식화하여 static method로 정의하고 사용한다. 이럴 경우에 반복되는 RestAssured 코드를 재사용 할 수 있고 테스트 코드가 더 간결해질 수 있다.

그럼 예시를 들며 사용법을 살펴보자.

UserRestAssuredCRUD.class

public class UserRestAssuredCRUD {
    public static ExtractableResponse<Response> postOriginUser(Map joinRequest) {
        return RestAssured
                .given().log().all()
                .queryParams(joinRequest)
                .when()
                .post("/user")
                .then()
                .log().all()
                .extract();
    }

}

나의 프로젝트에서 User 정보를 등록하는 postOriginUser 메소드를 가져와봤다.

이 메소드는 회원가입에 필요한 파라미터가 담긴 joinRequest라는 Map을 RestAssured를 통해 테스트하는 코드이다.

given에서 .log().all()을 통해서 HTTP Request의 Log를 콘솔창에 띄운다.
그리고 Query Parameter 형식을 지원하는 나의 회원가입 API에 변수를 넘기기 위해서 joinRequest를 첨부한다. -> Query Parameter, Path Parameter, Body 등 다양한 곳에 쉽게 객체만 넣으면 값이 변환되서 나간다 (이 부분이 RestAssured의 장점 중 하나다!)

when에서는 HTTP POST Method 형식으로 "/user"라는 Url에 요청을 보내기 위해 값들을 설정한다.

then에서는 응답으로 오는 모든 것들을 출력하기 위해 .log().all()을 해주고 .extract()를 통해서 HTTP Request를 보낸다.

CreateUserRequestUtil.class

@Component
public class CreateUserRequestUtil {

    public JoinRequest createJoinRequestWithUUID(String UUID) {
        return JoinRequest.builder()
                .email(UUID + "@" + UUID + ".com")
                .password(UUID)
                .loginProvider(LoginProvider.ORIGINAL)
                .nickname(UUID)
                .build();
    }

}

테스트에 사용 할 JoinRequest를 만드는 Util 클래스이다.

UserApiController.class

    @BeforeEach
    void beforeEach() {
        RestAssured.port = port;
    }
    
    @Test
    @DisplayName("프로필 이미지가 없는 회원가입 테스트")
    public void 프로필_이미지_를_포함하지않은_originJoin_을_테스트한다() throws Exception {

        String testUUID = UUID.randomUUID().toString();

        JoinRequest joinRequest = createUserRequestUtil.createJoinRequestWithUUID(testUUID);

        ExtractableResponse<Response> response = UserRestAssuredCRUD.postOriginUser(objectMapper.convertValue(joinRequest, Map.class));

        assertThat(response.statusCode()).isEqualTo(200);
    }

이제 진짜 테스트 코드이다.

나는 회원가입을 위한 JoinRequest에 넣을 파라미터를 UUID로 설정하였다.

그리고 우리가 만들었던 UserRestAssuredCRUD.postOriginUser에 ObjectMapper를 통해서 JoinRequest를 쿼리파라미터 형식으로 바꾸기위해 Map으로 바꿔준다.

Map으로 바꾼 값을 RestAssured를 통해 테스트해보고 응답으로 온 response의 HTTP StatusCode를 검증한다.

HTTP Request

HTTP Response


위와 같이 RestAssured는 로그를 통해서 내가 보낸 Request와 받은 Response 값을 가독성이 좋게 확인 할 수 있다!

파일을 첨부해서 테스트 해보기

나는 이번 프로젝트에서 회원가입을 할 때 이미지 파일을 첨부하면서 사용자의 프로필 이미지 기능을 넣어 보고 싶었다.

RestAssured를 통해서 이런 테스트가 가능할까? 걱정했는데 괜한 걱정이었다.

    public static ExtractableResponse<Response> postOriginUserWithProfileImage(Map joinRequest, File file){
        return RestAssured
                .given().log().all()
                .contentType(MediaType.MULTIPART_FORM_DATA_VALUE)
                .multiPart("multipartFile", file, MediaType.MULTIPART_FORM_DATA_VALUE)
                .queryParams(joinRequest)
                .when()
                .post("/user")
                .then()
                .log().all()
                .extract();
    }

위 내용에서 설명했듯이 나는 postOriginUserWithProfileImage 메서드를 만들어서 해결했다.
먼저 contentType을 Multipart/form-data 형식으로 설정하고
.multiPart()를 통해서 자바의 File을 첨부하면 된다.

나 같은 경우 처음에 컨트롤러에서 이미지 파일은 multipart/form-data 형식으로 보내야 되고, 파라미터는 application/json 형식으로 받게 설정했었다.

이런 복잡한 것도. multiPart("파라미터 이름", 파라미터, Meidatype.APPLICATION.JSON.VALUE)로 설정하면 이미지 파일과 Json 형식의 파라미터를 한 번에 보낼 수 있다. 너무 편하다!

    @Test
    @DisplayName("프로필 이미지가 있는 회원가입 테스트")
    public void 프로필_파일을_포함한_originJoin_을_테스트한다() throws Exception {

        String testUUID = UUID.randomUUID().toString();

        JoinRequest joinRequest = createUserRequestUtil.createJoinRequestWithUUID(testUUID);
        Resource resource = resourceLoader.getResource("classpath:profileimage/testimage.png");

        ExtractableResponse<Response> response = UserRestAssuredCRUD.postOriginUserWithProfileImage(objectMapper.convertValue(joinRequest, Map.class), resource.getFile());

        assertThat(response.statusCode()).isEqualTo(200);
    }

(postOriginUserWithProfileImage를 이용해 테스트하는 테스트 코드도 올려놓겠다.)

마치며

RestAssured는 테스트 코드 작성에 많은 편리함을 준다.
지금까지 복잡하게 파라미터를 받았던 나의 Controller 단의 요구도 모두 충족 시킬 수 있었고, 만약 에러가 나도 log를 통해서 파라미터가 어떻게 전달되었는지 쉽게 확인이 가능하다.

경험상 다음에 내가 작성할 주제인 Postman과 같이 사용할 때 더 편리하다. Postman에서 파라미터 값들을 설정하고 실제 보내질 Request를 확인할 수 있는 기능이 있는 데 이것을 RestAssured Request log와 비교하면서 잘못 들어가는 파라미터를 수정하면 테스트 코드 작성하는데 많은 도움이 된다.

또한 내가 맨 처음에 첨부한 Usage 사이트에서 RestAssured 사용법을 쉽게 찾을 수 있고 Stackoverflow에 많은 도움 글들이 있으니까 참고하면서 테스트 코드를 작성하자!

profile
이게 왜 틀리지... (나의 메모용 블로그)

0개의 댓글