A common pattern to communicate with backend systems today are RESTful HTTP resources, usually using JSON as the payload format. The standard for exposing your application’s functionality in a Java-EE application as REST resources is JAX-RS.
TestEE.fi allows you to test your application including your REST resources by combining the awesome and speedy Jetty servlet container with the JAX-RS reference implementation Jersey and integrating it seamlessly with the features you’ve already made yourself acquainted with in the previous installments.
Testing REST resources
In the previous parts of this series of articles we’ve covered the topics of mocking certain beans (adapters to external systems for example) during test execution in part 2 and had a deep dive into testing with JDBC and JPA in part 3.
Our approach in these examples was to have some bean (usually at the facade layer) injected in the test case and testing the business logic using method calls. While this approach allows for decent functional testing of your application’s business and persistence code, the presentation layer (i.e. your REST resources) is mostly out of reach.
While injecting the JAX-RS compliant REST resources into your test class is possible with TestEE.fi, you’d still be missing out much if the presentation logic that JAX-RS orchestrates at runtime, such as:
- Transformation of payloads (e.g. JSON) to transport objects (POJOs) via MessageBodyReaders and MessageBodyWriters
- Filtering REST requests and responses (e.g. for Logging or access control) using ContainerRequestFilters and ContainerResponseFilters
- Mapping your application’s exceptions to HTTP status codes with ExceptionMappers
…to only name a few of the very handy extensions JAX-RS allows for. Being able to include these features in your automated tests in order to see if your REST resources will work in production can be a huge benefit – even more so when you don’t have to start up your application container for it.
Using TestEE.fi’s REST extension
TestEE.fi doesn’t include the REST extension in the *-all depedencies (testeefi-junit4-all, testeefi-junit5-all, testeefi-cucumber-all) since Jersey and Jetty add some amount of classes to your test runtime classpath which can slow down test execution. So be sure to only include it in projects where you actually want to test your REST resources.
In order to have the REST testing extension available in your tests you need to add the testeefi-rest dependency.
In Maven a minimal setup looks like this:
In Gradle your dependency setup would look like this:
Once you have TestEE.fi’s REST extension in your test classpath, an interface called “RestServer” becomes available for @Resource injection in your test classes – it’s only purpose is to provide you with the HTTP port your test server is listening on and its declaration looks as follows:
The method getPort() returns a (randomly chosen) per-test-method port where Jetty listens and forwards all HTTP requests in the “/rest” context to Jersey.
Writing your first REST test with TestEE.fi
Since we will be testing HTTP REST resources we’re in need for a simple HTTP client to use in our test methods. I’ll be using the slim and simple okhttp library. You can of course use the HTTP client library of your choice, or even go for a HTTP client specifically designed for automated testing of REST interfaces, such as REST-Assured. I’ll also be using org.json in order to compose and parse JSON messages in my test code. For the sake of simplicity of this example, the REST resource we’ll be testing simply bounces back a JSON wrapped value we POST to it.
Since this is quite some amount of code at once let’s just digest is piece by piece.
- Line 1: Run your test with TestEE.fi
- Lines 5-6: The RestServer is injected into the test case as a @Resource
- Line 15: The port where the REST server is running is returned by RestServer.getPort()
- Line 18: Let’s have a closer look at how the URL is composed
- “http://localhost” is obvious – we’re running the test on your machine
- The port number returned from restServer is used
- The context root in TestEE.fi for REST resources is always “/rest”
- I’m using the REST application path “/example” (as can be seen in the sample code here)
- The name of the REST resource is “/resource” (as can be seen in the sample code here)
As you can see, TestEE.fi’s REST extension works exactly as your application container of choice would. The JAX-RS applications and resources are discovered automatically and exposed via HTTP at a port you can retrieve using the @Resource injected RestServer interface.
Be sure to have a look at the source code of the sample application from which the above test class was taken. The source code can be found here.
Conclusion
While testing your application’s functionality starting at the facade layer using method calls is a practical and recommended approach, it might be rewarding to instead include the REST resources in your automated tests, as well. TestEE.fi makes it easy to expose your application’s REST resources in a test case without the need to start an application container.
If you want to know more about advanced testing with TestEE.fi, be sure to check out the other posts of this series to get you up to speed quickly:
- Part 1: Introduction
- Part 2: Mocking with Mockito and EasyMock
- Part 3: JDBC and JPA
- Part 4: Cucumber JVM
- Part 6: JUnit 5
- Part 7: Static resources and Selenium (coming soon)
- Part 8: JMS and MDBs (coming soon)