Testing is never enough nowadays, and implementing integration tests can be a bit “boring”. So, why not utilize karate knocks to speed up your web service tests and make your life easier? Here's a brief introduction to the karate framework.
This article was originally published on viniciuspiedade.me and is republished here with permission from the author.
Karate enables you to script a sequence of calls to any kind of web-service and assert that the responses are as expected. It makes it very easy to build complex request payloads, traverse data within the responses, and chain data from responses into the next request. Karate’s payload validation engine can perform a ‘smart compare’ of two JSON or XML documents without being affected by white-space or the order in which data-elements actually appear, and you can opt to ignore fields that you choose.
Since Karate is built on top of Cucumber-JVM, you can run tests and generate reports like any standard Java project. But instead of Java – you write tests in a language designed to make dealing with HTTP, JSON, or XML simple.
Ok, now it's time for the code! We’ll spin up a local server with a json-server acting as our target web-service.
Create your awesome database as a json file:
Now, let the json-server spin-up a web-service automagically:
npm install json-server -g
Now we have our awesome service to perform a few tests using the powerful karate. To start coding, we’ll need:
- -Java 8
- -Maven (oh, really?)
- -Karate – Webservices testing with BDD-Like approach
- -Json-server – easy to use local mock server
Let’s create a new project with a karate maven archetype:
mvn archetype:generate \
Let’s make a small change on the pom.xml, adding entries to the testResources tag:
Now we have a basic karate structure!
We’ll use the project structure conventions based on Karate-Demo, but do a few things differently. First, your project classpath structure must consider the src/test/resources folder as a source folder because all karate config files are stored inside this folder, and they need to be at the root path of your test-classes like this:
- -src/main/java (Created by default for maven projects.)
- -src/test/resources (This is where all karate config files will live. We have to move karate-config.js and hogback-test.xml to this folder.)
- -src/test/java (This is where your features and tests will be organized. You can see an example created by a karate maven archetype.)
Here, you can see an example of the power of the karate framework:
With a single *.feature file using a Gherkin-like language, we're able to define a test against the ‘/posts’ endpoint, performing a POST with a post payload defined on the request body, asserting that it will return the HTTP status 200 and that the response body matches the expected post specification. Karate will interpret your Gherkin file with the power of Cucumber and its built-in StepDefinitions behind the scenes, as well as prepare request calls with all available http methods, deal with json, xml contents, and http headers, and make assertions with responses using its powerful jsonPath matcher and a lot more.
Organizing Your Feature Files
Karate provides a flexible way to run your feature files because it will run all files from above your current Java Test class recursively (including subfolders/packages). Based on this, we’ll organize our features on consumer and functionality hierarchy like below:
Let’s understand more about this project structure. In the root package, we have our consumer folders - one folder for each consumer, and inside the root of each consumer folder, we’ll have a Consumer Junit Test class responsible for running all tests for its consumer organized into functionalities (each functionality with a separated folder) from the Maven command line. Inside each functionality, we have one Junit class file, but with a Runner suffix and one or more feature files. That means that you can run all the features of the functionality of a specific consumer simply through your local IDE (eg. eclipse), running the *Runner.java class as a Junit Test class.
Run all features as a regressive test:
Run all features of the consumer1:
mvn test -Dtest=consumer1.Consumer1Test
Run all features of consumer1 posts functinality:
mvn test -Dtest=consumer1.posts.PostsCRUDRunner
Now, we’ll make a few improvements to the karate config files in order to make it eaiery to use in our projects. Below, you’ll see all the steps necessary to configure karate using the Buscapé convention:
Our karate-config.js file will look like this:
With this config file, we're defining a different baseUrl based on an environment variable called karate.env. If it’s filled with homolog value, all requests will hit our fake homolog server (http://homolog.myserver.com), and if no value was found for karate.env, it will then look to our local server - in this case, our json-server. We are then able to provide a different mock server port, or leave it as default 3000.
Coding Our Features
Let’s code our first feature of Consumer1: Post C.R.U.D.
Running Your First Test Locally With A Json-server
$ mvn test
You can specify the mock server port with -Dmock.server.port argument:
$ mvn test -DargLine=”-Dmock.server.port=8080″
Running Your Tests Pointing for the Homolog Server
$ mvn test -DargLine=”-Dkarate.env=homolog”
That’s it! Karate is an awesome project where you can easily create automated integration test pipelines inside your current CI/CD stack. Check out this project on my GitHub here, and enjoy!
Vinicius Piedade is a Java Developer at Avenue Code. He is exploring Kubernetes and is also passionate about photography.