Many web applications use a middleware layer to communicate data from the database to the user interface. That middleware layer is commonly a web service, or API. Having this additional layer provides an additional opportunity for testing. Rather than needing to run all tests as time-consuming, end-to-end tests, with this architecture, tests can be split into components and most of the business logic and data can be tested at the API level.
Here are a couple of open-source tools for testing APIs.
Note that for purposes of demonstration I am using a simple REST API that I am hosting locally using json-server.
Postman
One of the most commonly used tools for testing both SOAP and REST services is a GUI tool called Postman. Let’s walk through a brief sample REST API test. If you’d like to learn more about how to use Postman for SOAP service testing, refer to this blog post from their site.
Let’s break this down:
- This is where the type of request and the endpoint are defined. In this example, Postman is going to make a POST call to http://localhost:3000/blogposts, to create a new blog post resource.
- This is where the request body is defined. You can’t see from the screenshot, but in the Headers section, we are defining the Content-Type as application/JSON. This means this endpoint is expecting to get a JSON body and we can expect it to return JSON in the response body. In this example, our blog posts resource is quite simple and only requires two input fields: title and author, both of which take in string values. Once 1 and 2 are filled out, we hit the Send button to make the request.
- This is where the HTTP status response code that the API returns is displayed. While there are some exceptions, it is common for successful POST calls to respond with 201 Created, while GET, PUT, DELETE, etc. calls often respond with 200 OK. The fact that we are seeing 201 Created here means our request was valid and got processed properly by the API.
- Here is the response body that the API returns. On successful calls, like this one, you can expect to see either the full JSON object returned or at least some ID. On unsuccessful calls, you can expect to see an error message. In this example, the API returns the whole JSON object in the response body, however oftentimes you only get the ID back on POST calls and need to make a subsequent GET call to verify the data, so let’s go ahead and do that now.
- Similar to our previous request, this one is using the GET verb to fetch data from the API, as well as including an ID in the URL. This will specifically get the data for the blog post with ID 2.
- GET requests generally do not contain a body.
- As mentioned above, successful GET requests typically return 200 OK as the HTTP status code.
- The JSON response body contains the entire object for blog post with ID 2.
In this small example, it’s easy to manually verify that the data returned matches the data that we entered. However, Postman can do some of this work for us, making the test automated. Let’s see how.
Postman contains a Tests tab and some handy snippets on the right-hand side. Here you can see I’ve added a test to make sure we get back a 200 HTTP status request, and a test to verify the response body contains the elements and values we inputted in the POST call.
With Postman you can organize your tests into Collections and run them from the desktop application or using the CLI tool, which gives the flexibility of including Postman tests in your CICD solution.
RestAssured
For those, myself included, who prefer to get your hands a little dirty writing some code instead of using a GUI, a tool like RestAssured may be more suitable. RestAssured uses an HTTP client behind the scenes and contains several assertion helper methods. Despite the name, it too can be used for testing SOAP services. There’s no official blog post from them on that, so I’ll leave that up to you to search for one if you’re so inclined. Let’s jump right into an example using the same REST API endpoints from our examples above.
The snippet above is written in C# using the RestAssured C# library. Like before, let’s break this down.
- Make a POST call to http://localhost:3000/blogposts with the Content-Type header and the JSON body {“title”:”demo”,”author”:”cduggan”}
- RestAssured uses the BDD-style Given-When-Then syntax
- Returns the JSON response
- Using the built-in TestStatus method, verify the POST HTTP status response code is 201. This will throw an assertion failure if not.
- Retrieve the dynamically-created “ID” element’s value from the POST response, so that we may pass it to a GET call.
- Make a GET call to http://localhost:3000/blogposts/ where is the ID we retrieved and saved from step 3. Like the POST call we include the Content-Type header. Unlike the POST call we do not include a JSON body.
- Just like step 2, except we are now checking that the GET call responded with a 200 HTTP status code.
- Using the built-in TestBody and AssertAll methods, we first define the assertions that we want to run and then we execute the assertions. In this case, just like we did with Postman, we are making sure that title and author are equal to what we passed into the POST request.
For the sake of the demo, I put all of the logic in a single block of code, but you can benefit greatly by breaking each individual piece of logic into its own method for code reuse. Also, the built-in assertion methods are a bit lackluster so it may be a good idea to wrap them with some custom error handling to make parsing failures more readable. One of the reasons I prefer a tool like RestAssured is that it is so easily extendable. For example, RestAssured can be integrated with Cucumber, like so:
Given an integration like this, you’d need to use a JSON library to dynamically build the JSON object, and that can be a pretty fun task. If you missed my previous blog post talking about how wonderful Cucumber is, please give it a read. And because RestAssured (with or without Cucumber) is written in code, you can execute these tests as part of your team’s CICD plan pretty similarly to how you would unit tests (though these are post-deployment tests of course).
There are lots of other tools, both open-source and proprietary, on the market for testing APIs. This was just a sampling of two tools that I use on a regular basis. I also want to note that the example used to demo these tools was a particularly simple one and that API endpoints can be much more substantial (i.e. have nested elements and/or arrays, include complex business rules, etc.), as well as involve more actions; I only demonstrated Creating and Reading. Your tool of choice should be able to handle large, complex APIs with multiple actions (think C.R.U.D.), as Postman and RestAssured do.