Test de l'API REST avec Karaté

1. Vue d'ensemble

Dans cet article, nous présenterons Karate, un framework de test BDD (Behavior Driven Development) pour Java.

2. Karaté et BDD

Karate est construit sur Cucumber , un autre cadre de test BDD, et partage certains des mêmes concepts. L'un d'eux est l'utilisation d'un fichier Gherkin, qui décrit la fonctionnalité testée . Cependant, contrairement à Cucumber, les tests ne sont pas écrits en Java et sont entièrement décrits dans le fichier Gherkin.

Un fichier Gherkin est enregistré avec l' extension « .feature» . Il commence par le mot-clé Feature , suivi du nom de la fonction sur la même ligne. Il contient également différents scénarios de test, chacun commençant par le mot-clé Scénario et consistant en plusieurs étapes avec les mots-clés Étant donné , Quand , Alors , Et et Mais .

Plus d'informations sur le concombre et la structure Gherkin peuvent être trouvées ici.

3. Dépendances de Maven

Pour utiliser Karate dans un projet Maven, nous devons ajouter la dépendance karate-apache au pom.xml :

 com.intuit.karate karate-apache 0.6.0 

Nous aurons également besoin de la dépendance karate-junit4 pour faciliter les tests JUnit:

 com.intuit.karate karate-junit4 0.6.0 

4. Création de tests

Nous commencerons par écrire des tests pour certains scénarios courants dans un fichier de fonctionnalités Gherkin .

4.1. Test du code d'état

Écrivons un scénario qui teste un point de terminaison GET et vérifie s'il renvoie un code d'état HTTP 200 (OK):

Scenario: Testing valid GET endpoint Given url '//localhost:8097/user/get' When method GET Then status 200

Cela fonctionne évidemment avec tous les codes d'état HTTP possibles.

4.2. Tester la réponse

Écrivons un autre scénario qui teste que le point de terminaison REST renvoie une réponse spécifique:

Scenario: Testing the exact response of a GET endpoint Given url '//localhost:8097/user/get' When method GET Then status 200 And match $ == {id:"1234",name:"John Smith"}

L' opération de correspondance est utilisée pour la validation où « représente la réponse. Ainsi, le scénario ci-dessus vérifie que la réponse correspond exactement à " {id:" 1234 ", nom:" John Smith "}".

Nous pouvons également vérifier spécifiquement la valeur du champ id :

And match $.id == "1234"

L' opération de correspondance peut également être utilisée pour vérifier si la réponse contient certains champs. Ceci est utile lorsque seuls certains champs doivent être vérifiés ou lorsque tous les champs de réponse ne sont pas connus:

Scenario: Testing that GET response contains specific field Given url '//localhost:8097/user/get' When method GET Then status 200 And match $ contains {id:"1234"}

4.3. Validation des valeurs de réponse avec des marqueurs

Dans le cas où nous ne connaissons pas la valeur exacte renvoyée, nous pouvons toujours valider la valeur à l'aide de marqueurs - des espaces réservés pour les champs correspondants dans la réponse.

Par exemple, nous pouvons utiliser un marqueur pour indiquer si nous attendons une valeur nulle ou non:

  • #nul
  • #notnull

Ou nous pouvons utiliser un marqueur pour faire correspondre un certain type de valeur dans un champ:

  • #booléen
  • #nombre
  • #chaîne

D'autres marqueurs sont disponibles lorsque nous nous attendons à ce qu'un champ contienne un objet ou un tableau JSON:

  • #array
  • #objet

And there're markers for matching on a certain format or regular expression and one that evaluates a boolean expression:

  • #uuid — value conforms to the UUID format
  • #regex STR — value matches the regular expression STR
  • #? EXPR — asserts that the JavaScript expression EXPR evaluates to true

Finally, if we don't want any kind of check on a field, we can use the #ignore marker.

Let's rewrite the above scenario to check that the id field is not null:

Scenario: Test GET request exact response Given url '//localhost:8097/user/get' When method GET Then status 200 And match $ == {id:"#notnull",name:"John Smith"}

4.4. Testing a POST Endpoint With a Request Body

Let's look at a final scenario that tests a POST endpoint and takes a request body:

Scenario: Testing a POST endpoint with request body Given url '//localhost:8097/user/create' And request { id: '1234' , name: 'John Smith'} When method POST Then status 200 And match $ contains {id:"#notnull"}

5. Running Tests

Now that the test scenarios are complete, we can run our tests by integrating Karate with JUnit.

We'll use the @CucumberOptions annotation to specify the exact location of the Feature files:

@RunWith(Karate.class) @CucumberOptions(features = "classpath:karate") public class KarateUnitTest { //... }

To demonstrate the REST API, we'll use a WireMock server.

For this example, we mock all the endpoints that are being tested in the method annotated with @BeforeClass. We'll shut down the WireMock server in the method annotated with @AfterClass:

private static WireMockServer wireMockServer = new WireMockServer(WireMockConfiguration.options().port(8097)); @BeforeClass public static void setUp() throws Exception { wireMockServer.start(); configureFor("localhost", 8097); stubFor( get(urlEqualTo("/user/get")) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withBody("{ \"id\": \"1234\", name: \"John Smith\" }"))); stubFor( post(urlEqualTo("/user/create")) .withHeader("content-type", equalTo("application/json")) .withRequestBody(containing("id")) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withBody("{ \"id\": \"1234\", name: \"John Smith\" }"))); } @AfterClass public static void tearDown() throws Exception { wireMockServer.stop(); }

When we run the KarateUnitTest class, the REST Endpoints are created by the WireMock Server, and all the scenarios in the specified feature file are run.

6. Conclusion

In this tutorial, we looked at how to test REST APIs using the Karate Testing Framework.

Le code source complet et tous les extraits de code de cet article sont disponibles sur GitHub.