REST 보장 가이드

Jackson상의

방금 Spring 5 및 Spring Boot 2의 기본 사항에 초점을 맞춘 새로운 Learn Spring 과정을 발표했습니다 .

>> 과정 확인

1. 소개

REST-assured는 REST API의 테스트 및 유효성 검사를 단순화하도록 설계되었으며 Ruby 및 Groovy와 같은 동적 언어에서 사용되는 테스트 기술의 영향을 많이받습니다.

라이브러리는 물론 동사와 표준 HTTP 작업으로 시작하여 HTTP에 대한 견고한 지원을 제공하지만 이러한 기본 사항을 훨씬 뛰어 넘습니다.

이 가이드에서는 REST-assured탐색 하고 Hamcrest를 사용하여 어설 션을 수행 할 것입니다. 아직 Hamcrest에 익숙하지 않은 경우 먼저 자습서 : Hamcrest로 테스트를 살펴보아야합니다.

또한 REST-assured의 고급 사용 사례에 대해 알아 보려면 다른 문서를 확인하세요.

  • Groovy로 REST 보장
  • REST 보장을 통한 JSON 스키마 유효성 검사
  • REST가 보장 된 매개 변수, 헤더 및 쿠키

이제 간단한 예를 들어 보겠습니다.

2. 간단한 예제 테스트

시작하기 전에 테스트에 다음과 같은 정적 가져 오기가 있는지 확인합니다.

io.restassured.RestAssured.* io.restassured.matcher.RestAssuredMatchers.* org.hamcrest.Matchers.*

테스트를 간단하게 유지하고 주요 API에 쉽게 액세스하려면이 정보가 필요합니다.

이제 게임에 대한 일부 데이터를 노출하는 기본 베팅 시스템 인 간단한 예부터 시작하겠습니다.

{ "id": "390", "data": { "leagueId": 35, "homeTeam": "Norway", "visitingTeam": "England", }, "odds": [{ "price": "1.30", "name": "1" }, { "price": "5.25", "name": "X" }] }

이것이 로컬로 배포 된 API ( // localhost : 8080 / events? id = 390) 를 적중했을 때의 JSON 응답이라고 가정 해 보겠습니다 . :

이제 REST-assured를 사용하여 응답 JSON의 몇 가지 흥미로운 기능을 확인하겠습니다.

@Test public void givenUrl_whenSuccessOnGetsResponseAndJsonHasRequiredKV_thenCorrect() { get("/events?id=390").then().statusCode(200).assertThat() .body("data.leagueId", equalTo(35)); }

그래서 여기서 우리가 한 것은 – 엔드 포인트 / events? id = 390 에 대한 호출 이 데이터 개체 의 leagueId 가 35 인 JSON 문자열을 포함하는 본문으로 응답 하는지 확인했습니다 .

더 흥미로운 예를 살펴 보겠습니다. 배당률 배열에 가격이 1.305.25 인 레코드가 있는지 확인하고 싶다고 가정 해 보겠습니다 .

@Test public void givenUrl_whenJsonResponseHasArrayWithGivenValuesUnderKey_thenCorrect() { get("/events?id=390").then().assertThat() .body("odds.price", hasItems("1.30", "5.25")); }

3. REST 보장 설정

선호하는 종속성 도구가 Maven 인 경우 pom.xml 파일 에 다음 종속성을 추가 합니다.

 io.rest-assured rest-assured 3.3.0 test 

최신 버전을 얻으려면이 링크를 따르십시오.

REST-assured는 Hamcrest 매처의 힘을 이용하여 어설 션을 수행하므로 해당 종속성도 포함해야합니다.

 org.hamcrest hamcrest-all 2.1 

이 링크에서 항상 최신 버전을 사용할 수 있습니다.

4. 익명 JSON 루트 유효성 검사

객체가 아닌 기본 요소로 구성된 배열을 고려하십시오.

[1, 2, 3]

이를 익명 JSON 루트라고합니다. 즉, 키-값 쌍이 없지만 여전히 유효한 JSON 데이터입니다.

이러한 시나리오에서 $기호 또는 빈 문자열 ( "")을 경로 로 사용하여 유효성 검사를 실행할 수 있습니다 . // localhost : 8080 / json 을 통해 위의 서비스를 노출한다고 가정 하면 REST-assured로 다음과 같이 유효성을 검사 할 수 있습니다.

when().get("/json").then().body("$", hasItems(1, 2, 3));

또는 다음과 같이 :

when().get("/json").then().body("", hasItems(1, 2, 3));

5. 수레와 복식

REST-assured를 사용하여 REST 서비스를 테스트하기 시작할 때 JSON 응답의 부동 소수점 숫자가 기본 유형 float에 매핑된다는 것을 이해해야합니다 .

float 유형 의 사용은 java의 많은 시나리오 에서처럼 double 과 상호 교환 할 수 없습니다 .

적절한 사례는 다음과 같습니다.

{ "odd": { "price": "1.30", "ck": 12.2, "name": "1" } }

ck 값에 대해 다음 테스트를 실행한다고 가정합니다 .

get("/odd").then().assertThat().body("odd.ck", equalTo(12.2));

테스트중인 값이 응답의 값과 동일하더라도이 테스트는 실패합니다. 이것은 우리가 float 보다는 double 과 비교하기 때문 입니다.

To make it work, we have to explicitly specify the operand to the equalTo matcher method as a float, like so:

get("/odd").then().assertThat().body("odd.ck", equalTo(12.2f));

6. Specifying the Request Method

Typically, we would perform a request by calling a method such as get(), corresponding to the request method we want to use.

In addition, we can also specify the HTTP verb using the request() method:

@Test public void whenRequestGet_thenOK(){ when().request("GET", "/users/eugenp").then().statusCode(200); }

The example above is equivalent to using get() directly.

Similarly, we can send HEAD, CONNECT and OPTIONS requests:

@Test public void whenRequestHead_thenOK() { when().request("HEAD", "/users/eugenp").then().statusCode(200); }

POST request also follows a similar syntax and we can specify the body by using the with() and body() methods.

Therefore, to create a new Odd by sending a POST request:

@Test public void whenRequestedPost_thenCreated() { with().body(new Odd(5.25f, 1, 13.1f, "X")) .when() .request("POST", "/odds/new") .then() .statusCode(201); }

The Odd object sent as body will automatically be converted to JSON. We can also pass any String that we want to send as our POSTbody.

7. Default Values Configuration

We can configure a lot of default values for the tests:

@Before public void setup() { RestAssured.baseURI = "//api.github.com"; RestAssured.port = 443; }

Here, we're setting a base URI and port for our requests. Besides these, we can also configure the base path, root pat, and authentication.

Note: we can also reset to the standard REST-assured defaults by using:

RestAssured.reset();

8. Measure Response Time

Let's see how we can measure the response time using the time() and timeIn() methods of the Response object:

@Test public void whenMeasureResponseTime_thenOK() { Response response = RestAssured.get("/users/eugenp"); long timeInMS = response.time(); long timeInS = response.timeIn(TimeUnit.SECONDS); assertEquals(timeInS, timeInMS/1000); }

Note that:

  • time() is used to get response time in milliseconds
  • timeIn() is used to get response time in the specified time unit

8.1. Validate Response Time

We can also validate the response time – in milliseconds – with the help of simple longMatcher:

@Test public void whenValidateResponseTime_thenSuccess() { when().get("/users/eugenp").then().time(lessThan(5000L)); }

If we want to validate the response time in a different time unit, then we'll use the time() matcher with a second TimeUnit parameter:

@Test public void whenValidateResponseTimeInSeconds_thenSuccess(){ when().get("/users/eugenp").then().time(lessThan(5L),TimeUnit.SECONDS); }

9. XML Response Verification

Not only can it validate a JSON response, itcan validate XML as well.

Let's assume we make a request to //localhost:8080/employees and we get the following response:

  Jane Daisy f  

We can verify that the first-name is Jane like so:

@Test public void givenUrl_whenXmlResponseValueTestsEqual_thenCorrect() { post("/employees").then().assertThat() .body("employees.employee.first-name", equalTo("Jane")); }

We can also verify that all values match our expected values by chaining body matchers together like so:

@Test public void givenUrl_whenMultipleXmlValuesTestEqual_thenCorrect() { post("/employees").then().assertThat() .body("employees.employee.first-name", equalTo("Jane")) .body("employees.employee.last-name", equalTo("Daisy")) .body("employees.employee.sex", equalTo("f")); }

Or using the shorthand version with variable arguments:

@Test public void givenUrl_whenMultipleXmlValuesTestEqualInShortHand_thenCorrect() { post("/employees") .then().assertThat().body("employees.employee.first-name", equalTo("Jane"),"employees.employee.last-name", equalTo("Daisy"), "employees.employee.sex", equalTo("f")); }

10. XPath for XML

We can also verify our responses using XPath. Consider the example below that executes a matcher on the first-name:

@Test public void givenUrl_whenValidatesXmlUsingXpath_thenCorrect() { post("/employees").then().assertThat(). body(hasXPath("/employees/employee/first-name", containsString("Ja"))); }

XPath also accepts an alternate way of running the equalTo matcher:

@Test public void givenUrl_whenValidatesXmlUsingXpath2_thenCorrect() { post("/employees").then().assertThat() .body(hasXPath("/employees/employee/first-name[text()='Jane']")); }

11. Logging Test Details

11.1. Log Request Details

First, let's see how to log entire request details using log().all():

@Test public void whenLogRequest_thenOK() { given().log().all() .when().get("/users/eugenp") .then().statusCode(200); }

This will log something like this:

Request method: GET Request URI: //api.github.com:443/users/eugenp Proxy:  Request params:  Query params:  Form params:  Path params:  Multiparts:  Headers: Accept=*/* Cookies:  Body: 

To log only specific parts of the request, we have the log() method in combination with params(), body(), headers(), cookies(), method(), path() eg log.().params().

Note that other libraries or filters used may alter what's actually sent to the server, so this should only be used to log the initial request specification.

11.2. Log Response Details

Similarly, we can log the response details.

In the following example we're logging the response body only:

@Test public void whenLogResponse_thenOK() { when().get("/repos/eugenp/tutorials") .then().log().body().statusCode(200); }

Sample output:

{ "id": 9754983, "name": "tutorials", "full_name": "eugenp/tutorials", "private": false, "html_url": "//github.com/eugenp/tutorials", "description": "The \"REST With Spring\" Course: ", "fork": false, "size": 72371, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "//api.github.com/licenses/mit" }, ... }

11.3. Log Response if Condition Occurred

We also have the option of logging the response only if an error occurred or the status code matches a given value:

@Test public void whenLogResponseIfErrorOccurred_thenSuccess() { when().get("/users/eugenp") .then().log().ifError(); when().get("/users/eugenp") .then().log().ifStatusCodeIsEqualTo(500); when().get("/users/eugenp") .then().log().ifStatusCodeMatches(greaterThan(200)); }

11.4. Log if Validation Failed

We can also log both request and response only if our validation failed:

@Test public void whenLogOnlyIfValidationFailed_thenSuccess() { when().get("/users/eugenp") .then().log().ifValidationFails().statusCode(200); given().log().ifValidationFails() .when().get("/users/eugenp") .then().statusCode(200); }

이 예에서는 상태 코드가 200인지 확인하려고합니다. 이것이 실패하는 경우에만 요청과 응답이 기록됩니다.

12. 결론

이 튜토리얼에서 우리는 REST 보장 프레임 워크를 탐색 하고 RESTful 서비스를 테스트하고 응답을 검증하는 데 사용할 수있는 가장 중요한 기능을 살펴 보았습니다.

이러한 모든 예제와 코드 조각의 전체 구현은 REST 보증 GitHub 프로젝트에서 찾을 수 있습니다.

잭슨 바닥

방금 Spring 5 및 Spring Boot 2의 기본 사항에 초점을 맞춘 새로운 Learn Spring 과정을 발표했습니다 .

>> 과정 확인