Overview
In the previous articles, we learnt different concepts about JAX-RS. It’s interesting see how many things we can actually do with this spec. However, it’s also important to prove that our code actually works. Today, we are going to take a look on testing: How to test the JAX-RS resources in Java?
I’m using JUnit 4, Jersey, and Grizzly Server. More detail will be explained later on. After reading this article, you will understand:
- How to set up a Grizzly Server for tests
- How to create a HTTP request
- How to assert response
- Limits of API testing
Set Up Grizzly Server for Tests
Before creating any tests, we need to set up a server for hosting the JAX-RS
resources. In my example, I use Grizzly server. In order to configure it, you
need to define which JAX-RS Application
you want to deploy; the URI where the
server will be running; and actually start the server with these configuration
properties. As for tear down, use shutdownNow()
method to immediately shut
down the HttpServer
instance.
Why Grizzly Server? I choose Grizzly because it’s a lightweight server, and is actually being used by the Jersey Team for their tests. In reality, you might need to deploy other Java server: Jetty, Tomcat, WildFly, … It depends really on the context. In my daily work, we use Nuxeo Server (built on top of Tomcat). In my side projects, I use Jetty.
Create a HTTP request
Now the server is ready, we can write test. The first step is to create a HTTP
request. The creation can be done using methods in Client API:
Client#target(...)
. These methods accept String, URI, URI Builder, and Link
as input parameter type. For example, create web target using a String:
Once created, you can use path
to define the path to a specific resource. For
example, if you need to request book 1 defined by the following URL:
http://localhost:8080/books/1
You can do:
For more information about using JAX-RS Client API, see my other post: JAX-RS Client API.
Assert Response
Once the response is returned, you can assert it using JUnit. I think the most common use cases are assertions on the status code and the entity (response body).
Assert HTTP status:
Note that class javax.ws.rs.core.Response
actually provides 2 similar methods
for getting status: int getStatus()
and StatusType getStatusInfo()
.
Personally, I prefer using getStatus()
for assertion, because comparing
numbers is easier than compare enum, thus less chance to fail.
Assert HTTP body:
Asserting other information are similar.
Limits of Testing API
While testing API looks really simple on this article, it is not in reality. Here’re some factors that you might consider:
- The number input params of a resource method. A method might use form params, query params, path params, entity, header params, cookie params, etc for its logic. The number of parameters can change dramatically the complexity of preparation and the possible scenario to test.
- The complexity of server setup. The complexity depends on number of layers on the backend, the business logic, the persistence, the frameworks used etc. The more complex it is, the harder to maintain and the slower to start.
- REST layer is supposed to be simple. In theory, the REST layer is supposed to be simple. It should avoid having any complex logic and pass input values to business layer right after reception. Therefore, the test effort should be focus on business layer, where unit tests are easier to write and maintain.
- Possible errors. When testing APIs, we often use a partial deployment of the server and it may not reflect to the real setup of the production environment. Firewall, proxy, authentication services, … many factors are not taken into account when testing APIs. Thus, possible errors might not be discovered by these tests.
- Maintainability. The slowness of execution and the complexity of setup the server will introduce a big effort for maintaining these tests in the long term.
Conclusion
In this article, we’ve seen how to set up and tear down a Grizzly Server for testing JAX-RS resources. We learnt how to create a HTTP request and assert the response using JUnit 4. At the end, I also share some thoughts about the limits of testing API in reality.
The entire JAX-RS series is written in TDD (Test Driven Development) way, you
can visit my GitHub repository jaxrs-2.x-demo and search *IT.java
to see
how those integration tests are written. Hope you enjoy this article, see you
the next time!