Ein Leitfaden für REST-versichert

Jackson Top

Ich habe gerade den neuen Learn Spring- Kurs angekündigt , der sich auf die Grundlagen von Spring 5 und Spring Boot 2 konzentriert:

>> Überprüfen Sie den Kurs

1. Einleitung

REST-Assured wurde entwickelt, um das Testen und Validieren von REST-APIs zu vereinfachen. Es wird stark von Testtechniken beeinflusst, die in dynamischen Sprachen wie Ruby und Groovy verwendet werden.

Die Bibliothek bietet eine solide Unterstützung für HTTP, angefangen natürlich mit den Verben und Standard-HTTP-Operationen, aber auch weit über diese Grundlagen hinaus.

In diesem Handbuch werden wir REST-versichert untersuchen und Hamcrest verwenden, um Behauptungen aufzustellen. Wenn Sie mit Hamcrest noch nicht vertraut sind, sollten Sie zuerst das Tutorial auffrischen: Testen mit Hamcrest.

Weitere Informationen zu fortgeschritteneren Anwendungsfällen von REST-versichert finden Sie in unseren anderen Artikeln:

  • REST-versichert mit Groovy
  • JSON-Schema-Validierung mit REST-Sicherheit
  • Parameter, Header und Cookies mit REST-Sicherheit

Lassen Sie uns nun mit einem einfachen Beispiel eintauchen.

2. Einfacher Beispieltest

Bevor wir beginnen, stellen wir sicher, dass unsere Tests die folgenden statischen Importe haben:

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

Wir werden das brauchen, um die Tests einfach zu halten und einfachen Zugriff auf die Haupt-APIs zu haben.

Beginnen wir nun mit dem einfachen Beispiel - einem grundlegenden Wettsystem, das einige Daten für Spiele bereitstellt:

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

Angenommen, dies ist die JSON-Antwort beim Aufrufen der lokal bereitgestellten API - // localhost: 8080 / events? Id = 390. ::

Lassen Sie uns nun REST-versichert verwenden, um einige interessante Funktionen der Antwort JSON zu überprüfen:

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

Was wir hier getan haben, ist - wir haben überprüft, dass ein Aufruf des Endpunkts / der Ereignisse? Id = 390 mit einem Body antwortet, der einen JSON-String enthält, dessen Liga-ID des Datenobjekts 35 ist.

Schauen wir uns ein interessanteres Beispiel an. Angenommen, Sie möchten überprüfen, ob das Odds- Array Datensätze mit den Preisen 1,30 und 5,25 enthält :

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

3. REST-sicheres Setup

Wenn Ihr bevorzugtes Abhängigkeitstool Maven ist, fügen wir der Datei pom.xml die folgende Abhängigkeit hinzu :

 io.rest-assured rest-assured 3.3.0 test 

Um die neueste Version zu erhalten, folgen Sie diesem Link.

REST-versichert nutzt die Macht der Hamcrest-Matcher, um seine Behauptungen zu erfüllen. Daher müssen wir auch diese Abhängigkeit berücksichtigen:

 org.hamcrest hamcrest-all 2.1 

Die neueste Version ist immer unter diesem Link verfügbar.

4. Anonyme JSON-Stammvalidierung

Stellen Sie sich ein Array vor, das eher aus Grundelementen als aus Objekten besteht:

[1, 2, 3]

Dies wird als anonymer JSON-Stamm bezeichnet. Dies bedeutet, dass kein Schlüssel-Wert-Paar vorhanden ist und dennoch gültige JSON-Daten vorhanden sind.

In einem solchen Szenario können wir die Validierung ausführen, indem wir das $Symbol oder einen leeren String ("") als Pfad verwenden. Angenommen, wir stellen den oben genannten Service über // localhost: 8080 / json zur Verfügung, dann können wir ihn mit REST-versichert wie folgt validieren:

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

oder so:

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

5. Floats und Doubles

Wenn wir REST-Assured zum Testen unserer REST-Services verwenden, müssen wir verstehen, dass Gleitkommazahlen in JSON-Antworten dem primitiven Typ float zugeordnet sind.

Die Verwendung des Float- Typs ist nicht mit Double austauschbar, wie dies bei vielen Szenarien in Java der Fall ist.

Ein typisches Beispiel ist diese Antwort:

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

Angenommen, wir führen den folgenden Test für den Wert von ck durch :

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

Dieser Test schlägt auch dann fehl, wenn der Wert, den wir testen, dem Wert in der Antwort entspricht. Dies liegt daran, dass wir eher mit einem Double als mit einem Float vergleichen .

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); }

In diesem Beispiel möchten wir überprüfen, ob der Statuscode 200 lautet. Nur wenn dies fehlschlägt, werden die Anforderung und die Antwort protokolliert.

12. Schlussfolgerung

In diesem Tutorial haben wir das REST-gesicherte Framework untersucht und seine wichtigsten Funktionen untersucht, mit denen wir unsere RESTful-Services testen und ihre Antworten validieren können.

Die vollständige Implementierung all dieser Beispiele und Codefragmente finden Sie im REST-gesicherten GitHub-Projekt.

Jackson unten

Ich habe gerade den neuen Learn Spring- Kurs angekündigt , der sich auf die Grundlagen von Spring 5 und Spring Boot 2 konzentriert:

>> Überprüfen Sie den Kurs