Erkundung des Jersey Test Framework

1. Übersicht

In diesem Tutorial werfen wir einen Blick auf das Jersey Test Framework und sehen, wie wir damit schnell Integrationstests schreiben können.

Wie wir bereits in früheren Artikeln gesehen haben, ist Jersey ein Open-Source-Framework für die Entwicklung von RESTful Web Services . Weitere Informationen zu Jersey finden Sie in unserer Einführung zum Erstellen einer API mit Jersey und Spring - hier.

2. Anwendungs-Setup

Das Jersey Test Framework ist ein Tool, mit dem wir die korrekte Implementierung unserer serverseitigen Komponenten überprüfen können. Wie wir später sehen werden, bietet es eine schnelle und unkomplizierte Möglichkeit, Integrationstests zu schreiben, und kann die Kommunikation mit unseren HTTP-APIs sehr gut handhaben.

Ebenso funktioniert es fast sofort und ist einfach in unsere Maven-basierten Projekte zu integrieren . Das Framework basiert hauptsächlich auf JUnit, obwohl es auch mit TestNG verwendet werden kann, wodurch es in fast allen Umgebungen verwendet werden kann.

Im nächsten Abschnitt werden wir sehen, welche Abhängigkeiten wir unserer Anwendung hinzufügen müssen, um das Framework zu verwenden.

2.1. Maven-Abhängigkeiten

Fügen wir zunächst die Kernabhängigkeit des Jersey Test Framework zu unserer pom.xml hinzu :

 org.glassfish.jersey.test-framework jersey-test-framework-core 2.27 test 

Wie immer können wir die neueste Version von Maven Central erhalten.

Fast alle Jersey-Tests verwenden die defacto Grizzly-Testbehälterfabrik, die wir auch hinzufügen müssen:

 org.glassfish.jersey.test-framework.providers jersey-test-framework-provider-grizzly2 2.27 test 

Wieder können wir die neueste Version in Maven Central finden.

3. Erste Schritte

In diesem nächsten Abschnitt werden die grundlegenden Schritte behandelt, die zum Schreiben eines einfachen Tests erforderlich sind.

Zunächst testen wir die einfache Ressource " Grüße" auf unserem Server:

@Path("/greetings") public class Greetings { @GET @Path("/hi") public String getHiGreeting() { return "hi"; } } 

3.1. Test konfigurieren

Definieren wir nun unsere Testklasse:

public class GreetingsResourceIntegrationTest extends JerseyTest { @Override protected Application configure() { return new ResourceConfig(Greetings.class); } //... } 

Im obigen Beispiel sehen wir, dass unser Test JerseyTest in Unterklassen unterteilen muss, um einen Test mit dem Jersey Test Framework zu entwickeln .

Als Nächstes überschreiben wir die Konfigurationsmethode , die eine benutzerdefinierte Ressourcenkonfiguration für unseren Test zurückgibt und nur die Begrüßungsressource enthält . Dies ist natürlich die Ressource, die wir testen möchten.

3.2. Schreiben Sie unseren ersten Test

Beginnen wir mit dem Testen einer einfachen GET-Anfrage über unsere Begrüßungs-API:

@Test public void givenGetHiGreeting_whenCorrectRequest_thenResponseIsOkAndContainsHi() { Response response = target("/greetings/hi").request() .get(); assertEquals("Http Response should be 200: ", Status.OK.getStatusCode(), response.getStatus()); assertEquals("Http Content-Type should be: ", MediaType.TEXT_HTML, response.getHeaderString(HttpHeaders.CONTENT_TYPE)); String content = response.readEntity(String.class); assertEquals("Content of ressponse is: ", "hi", content); } 

Beachten Sie, dass wir vollen Zugriff auf die HTTP-Antwort haben. So können wir beispielsweise den Statuscode überprüfen, um sicherzustellen, dass der Vorgang tatsächlich erfolgreich war, oder mit dem tatsächlichen Hauptteil der Antwort arbeiten .

Lassen Sie uns genauer erklären, was wir im obigen Beispiel tun:

  1. Senden Sie eine HTTP-GET-Anfrage an '/ greetings / hi'.
  2. Überprüfen Sie den HTTP-Statuscode und die Antwortheader für den Inhaltstyp
  3. Test Der Inhalt der Antwort enthält die Zeichenfolge "hi"

4. Testen von GET zum Abrufen von Ressourcen

Jetzt haben wir die grundlegenden Schritte zum Erstellen von Tests gesehen. Testen wir die einfache Frucht-API, die wir im ausgezeichneten Artikel zum Jersey MVC-Support vorgestellt haben.

4.1. Holen Sie sich Plain JSON

Im folgenden Beispiel arbeiten wir mit dem Antworttext als Standard-JSON-Zeichenfolge:

@Test public void givenFruitExists_whenSearching_thenResponseContainsFruit() { final String json = target("fruit/search/strawberry").request() .get(String.class); assertThat(json, containsString("{\"name\":\"strawberry\",\"weight\":20}")); }

4.2. Entität anstelle von JSON abrufen

Wir können die Antwort auch direkt einer Ressourcenentitätsklasse zuordnen - zum Beispiel:

 @Test public void givenFruitExists_whenSearching_thenResponseContainsFruitEntity() { final Fruit entity = target("fruit/search/strawberry").request() .get(Fruit.class); assertEquals("Fruit name: ", "strawberry", entity.getName()); assertEquals("Fruit weight: ", Integer.valueOf(20), entity.getWeight()); }

Dieses Mal geben wir den Java-Typ an, in den die Antwortentität in der get- Methode konvertiert wird - ein Fruit- Objekt.

5. Testen des POST zum Erstellen von Ressourcen

Um eine neue Ressource in unserer API zu erstellen, werden wir POST-Anforderungen gut nutzen. Im nächsten Abschnitt erfahren Sie, wie Sie diesen Teil unserer API testen.

5.1. Post Plain JSON

Beginnen wir mit der Veröffentlichung eines einfachen JSON-Strings, um die Erstellung einer neuen Fruchtressource zu testen:

@Test public void givenCreateFruit_whenJsonIsCorrect_thenResponseCodeIsCreated() { Response response = target("fruit/created").request() .post(Entity.json("{\"name\":\"strawberry\",\"weight\":20}")); assertEquals("Http Response should be 201 ", Status.CREATED.getStatusCode(), response.getStatus()); assertThat(response.readEntity(String.class), containsString("Fruit saved : Fruit [name: strawberry colour: null]")); }

Im obigen Beispiel verwenden wir die post- Methode, die einen Entity- Objektparameter verwendet. Wir verwenden die bequeme json- Methode, um eine Entität aus der entsprechenden JSON-Zeichenfolge zu erstellen .

5.2. Post Entity Instead of JSON

As we've already seen with get requests we can also post a Resource entity class directly – for example:

@Test public void givenCreateFruit_whenFruitIsInvalid_thenResponseCodeIsBadRequest() { Fruit fruit = new Fruit("Blueberry", "purple"); fruit.setWeight(1); Response response = target("fruit/create").request(MediaType.APPLICATION_JSON_TYPE) .post(Entity.entity(fruit, MediaType.APPLICATION_JSON_TYPE)); assertEquals("Http Response should be 400 ", 400, response.getStatus()); assertThat(response.readEntity(String.class), containsString("Fruit weight must be 10 or greater")); }

This time we use the entity method to post our Fruit entity and also specify the media type as JSON.

5.3. Form Submissions Using POST

In our final post example we will see how to test form submissions via a post request:

@Test public void givenCreateFruit_whenFormContainsNullParam_thenResponseCodeIsBadRequest() { Form form = new Form(); form.param("name", "apple"); form.param("colour", null); Response response = target("fruit/create").request(MediaType.APPLICATION_FORM_URLENCODED) .post(Entity.form(form)); assertEquals("Http Response should be 400 ", 400, response.getStatus()); assertThat(response.readEntity(String.class), containsString("Fruit colour must not be null")); }

Similarly, we make use of the Entity class but this time pass a form which contains a number of parameters to our post request.

6. Testing Other HTTP Verbs

Sometimes we need to test other HTTP endpoints such as PUT and DELETE. This is of course perfectly possible using the Jersey Test Framework.

Let's see a simple PUT example:

@Test public void givenUpdateFruit_whenFormContainsBadSerialParam_thenResponseCodeIsBadRequest() { Form form = new Form(); form.param("serial", "2345-2345"); Response response = target("fruit/update").request(MediaType.APPLICATION_FORM_URLENCODED) .put(Entity.form(form)); assertEquals("Http Response should be 400 ", 400, response.getStatus()); assertThat(response.readEntity(String.class), containsString("Fruit serial number is not valid")); }

Once we have called the request method, we can invoke any HTTP method on the current request object.

7. Additional Features

The Jersey test framework contains a number of additional configuration properties which can help aid debugging and testing.

In the next example we'll see how to programmatically enable a feature with a given name:

public class FruitResourceIntegrationTest extends JerseyTest { @Override protected Application configure() { enable(TestProperties.LOG_TRAFFIC); enable(TestProperties.DUMP_ENTITY); //...

When we create and configure our Jersey application under test. We can also enable additional properties. In this case, we enable two logging properties – LOG_TRAFFIC and DUMP_ENTITYwhich will provide useful additional logging and debug information during test runs.

8. Supported Containers

As we've already mentioned the defacto container used when writing tests with the Jersey Test Framework is Grizzly. However, a number of other containers are supported:

  • In-Memory container
  • HttpServer from Oracle JDK
  • Simple container (org.simpleframework.http
  • Jetty container (org.eclipse.jetty)

For more information on how to configure these containers, please see the documentation here.

9. Conclusion

To summarize, in this tutorial, we’ve explored the Jersey Test Framework. First, we started by introducing how to configure the Jersey Test Framework and then we saw how to write a test for a very simple API.

In the next section, we saw how to write tests for a variety of GET and POST API endpoints. Finally, we looked at some additional features and the containers that the Jersey Test Framework supports.

Wie immer ist der vollständige Quellcode des Artikels auf GitHub verfügbar.