Test API REST avec Karaté
1. Vue d'ensemble
Dans cet article, nous présenteronsKarate, un framework de test BDD (Behavior Driven Development) pour Java.
2. Karaté et BDD
Karate isbuilt on top of Cucumber, un autre cadre de test BDD, et partage certains des mêmes concepts. L'un d'eux estthe use of a Gherkin file, which describes the tested feature. Cependant, contrairement à Cucumber, les tests ne sont pas écrits en Java et sont décrits en détail 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éScenario et consistant en plusieurs étapes avec les mots-clésGiven,When,Then,And et But.
Plus d'informations sur le concombre et la structure Gherkin peuvent être trouvéeshere.
3. Dépendances Maven
Pour utiliser le karaté dans un projet Maven, nous devons ajouter la dépendancekarate-apache auxpom.xml:
com.intuit.karate
karate-apache
0.6.0
Nous aurons également besoin de la dépendancekarate-junit4 pour faciliter les tests JUnit:
com.intuit.karate
karate-junit4
0.6.0
4. Créer des tests
Nous allons commencer par écrire des tests pour certains scénarios courants dans un fichier GherkinFeature.
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 HTTP200 (OK):
Scenario: Testing valid GET endpoint
Given url 'http://localhost:8080/user/get'
When method GET
Then status 200
Cela fonctionne évidemment avec tous les codes de statut 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 'http://localhost:8080/user/get'
When method GET
Then status 200
And match $ == {id:"1234",name:"John Smith"}
The match operation is used for the validation où «$' représente la réponse. Ainsi, le scénario ci-dessus vérifie que la réponse correspond exactement à «\{id:”1234″,name:”John Smith”}'.
Nous pouvons également vérifier spécifiquement la valeur du champid:
And match $.id == "1234"
The match operation can also be used to check if the response contains certain fields. 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 'http://localhost:8080/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 en utilisantmarkers - 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 valeurnull ou non:
-
#null
-
#notnull
Ou nous pouvons utiliser un marqueur pour faire correspondre un certain type de valeur dans un champ:
-
#boolean
-
#number
-
#string
D'autres marqueurs sont disponibles pour lorsqu'un champ contient un objet ou un tableau JSON:
-
#array
-
#object
Et il existe des marqueurs de correspondance sur un certain format ou une expression régulière et un qui évalue une expression booléenne:
-
La valeur#uuid — est conforme au format UUID
-
La valeur de#regex STR — correspond à l'expression régulièreSTR
-
#? EXPR — affirme que l'expression JavaScriptEXPR est évaluée àtrue
Enfin, si nous ne voulons aucun type de contrôle sur un champ, nous pouvons utiliser le marqueur#ignore.
Réécrivons le scénario ci-dessus pour vérifier que le champid n'est pasnull:
Scenario: Test GET request exact response
Given url 'http://localhost:8080/user/get'
When method GET
Then status 200
And match $ == {id:"#notnull",name:"John Smith"}
4.4. Test d'un point de terminaison POST avec un corps de requête
Examinons un dernier scénario qui teste un point de terminaison POST et prend un corps de requête:
Scenario: Testing a POST endpoint with request body
Given url 'http://localhost:8080/user/create'
And request { id: '1234' , name: 'John Smith'}
When method POST
Then status 200
And match $ contains {id:"#notnull"}
5. Exécution de tests
Maintenant que les scénarios de test sont terminés, nous pouvons exécuter nos tests en intégrant Karaté à JUnit.
Nous utiliserons l'annotation@CucumberOptions pour spécifier l'emplacement exact des fichiersFeature:
@RunWith(Karate.class)
@CucumberOptions(features = "classpath:karate")
public class KarateUnitTest {
//...
}
Pour illustrer l'API REST, nous utiliserons unWireMock server.
Pour cet exemple, nous nous moquons de tous les points de terminaison testés dans la méthode annotée avec@BeforeClass. Nous allons arrêter le serveur WireMock dans la méthode annotée avec@AfterClass:
private static WireMockServer wireMockServer
= new WireMockServer();
@BeforeClass
public static void setUp() throws Exception {
wireMockServer.start();
configureFor("localhost", 8080);
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();
}
Lorsque nous exécutons la classeKarateUnitTest, les points de terminaison REST sont créés par le serveur WireMock et tous les scénarios du fichier de fonctionnalités spécifié sont exécutés.
6. Conclusion
Dans ce didacticiel, nous avons examiné comment tester les API REST à l'aide de Karate Testing Framework.
Le code source complet et tous les extraits de code de cet article sont disponiblesover on GitHub.