Teste da API REST com Karate
1. Visão geral
Neste artigo, apresentaremosKarate, uma estrutura de teste Behavior Driven Development (BDD) para Java.
2. Karate e BDD
Karate isbuilt on top of Cucumber, outra estrutura de teste do BDD e compartilha alguns dos mesmos conceitos. Um deles éthe use of a Gherkin file, which describes the tested feature. No entanto, ao contrário do Cucumber, os testes não são escritos em Java e são totalmente descritos no arquivo Gherkin.
Um arquivo Gherkin é salvo com a extensão “.feature”. Ele começa com a palavra-chaveFeature, seguida pelo nome do recurso na mesma linha. Ele também contém diferentes cenários de teste, cada um começando com a palavra-chaveScenario e consistindo em várias etapas com as palavras-chaveGiven,When,Then,And, e But.
Mais sobre o Pepino e a estrutura do Maxixe pode ser encontradohere.
3. Dependências do Maven
Para fazer uso do Karate em um projeto Maven, precisamos adicionar a dependênciakarate-apache aopom.xml:
com.intuit.karate
karate-apache
0.6.0
Também precisaremos da dependênciakarate-junit4 para facilitar o teste JUnit:
com.intuit.karate
karate-junit4
0.6.0
4. Criando testes
Começaremos escrevendo testes para alguns cenários comuns em um arquivo GherkinFeature.
4.1. Testando o código de status
Vamos escrever um cenário que testa um endpoint GET e verifica se ele retorna um código de status HTTP200 (OK):
Scenario: Testing valid GET endpoint
Given url 'http://localhost:8080/user/get'
When method GET
Then status 200
Obviamente, isso funciona com todos os códigos de status HTTP possíveis.
4.2. Testando a Resposta
Vamos escrever outro cenário que testa se o endpoint REST retorna uma resposta específica:
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 onde ‘$' representa a resposta. Portanto, o cenário acima verifica se a resposta corresponde exatamente a ‘\{id:”1234″,name:”John Smith”}'.
Também podemos verificar especificamente o valor do campoid:
And match $.id == "1234"
The match operation can also be used to check if the response contains certain fields. Isso é útil quando apenas alguns campos precisam ser verificados ou quando nem todos os campos de resposta são conhecidos:
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. Validando Valores de Resposta com Marcadores
No caso em que não sabemos o valor exato que é retornado, ainda podemos validar o valor usandomarkers - marcadores para campos correspondentes na resposta.
Por exemplo, podemos usar um marcador para indicar se esperamos um valornull ou não:
-
#null
-
#notnull
Ou podemos usar um marcador para corresponder a um determinado tipo de valor em um campo:
-
#boolean
-
#number
-
#string
Outros marcadores estão disponíveis para quando esperamos que um campo contenha um objeto ou matriz JSON:
-
#array
-
#object
E há marcadores para correspondência em um determinado formato ou expressão regular e um que avalia uma expressão booleana:
-
O valor#uuid — está em conformidade com o formato UUID
-
O valor de#regex STR — corresponde à expressão regularSTR
-
#? EXPR — afirma que a expressão JavaScriptEXPR avalia paratrue
Finalmente, se não quisermos nenhum tipo de verificação em um campo, podemos usar o marcador#ignore.
Vamos reescrever o cenário acima para verificar se o campoid não énull:
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. Testando um Endpoint POST com um corpo de solicitação
Vejamos um cenário final que testa um endpoint POST e leva um corpo de solicitação:
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. Executando testes
Agora que os cenários de teste estão completos, podemos executar nossos testes integrando o Karate ao JUnit.
Usaremos a anotação@CucumberOptions para especificar a localização exata dos arquivosFeature:
@RunWith(Karate.class)
@CucumberOptions(features = "classpath:karate")
public class KarateUnitTest {
//...
}
Para demonstrar a API REST, usaremos umWireMock server.
Para este exemplo, simulamos todos os terminais que estão sendo testados no método anotado com@BeforeClass. Desligaremos o servidor WireMock no método anotado com@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();
}
Quando executamos a classeKarateUnitTest, os Endpoints REST são criados pelo WireMock Server e todos os cenários no arquivo de recurso especificado são executados.
6. Conclusão
Neste tutorial, vimos como testar APIs REST usando o Karate Testing Framework.
O código-fonte completo e todos os trechos de código para este artigo podem ser encontradosover on GitHub.