Test Jersey Rest Service with JUnit
In this example we show you how to test Jersey Rest Services with JUnit. JerseyTest is developed by Jersey themselves in order to facilitate the testing of their rest services. You can really easily test your services against a set of preconfigured containers or even an external container. In this tutorial we’ll focus on a preconfigured container, namely jetty.
Maven dependencies
Here is the pom.xml file I used in order to configure jersey, junit and jetty. Also a cool feature is that we can run these unit tests in parallel which leads to better performance when dealing with many unit tests. We also use the maven-war-plugin to tell maven not to fail over the missing web.xml file. Because we don’t need it for this application.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.memorynotfound.webservice.rs.jersey</groupId>
<artifactId>unit-test-junit</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>JERSEY - ${project.artifactId}</name>
<url>https://memorynotfound.com</url>
<properties>
<jersey.version>2.22.1</jersey.version>
<junit.version>4.12</junit.version>
<surefire.version>2.19</surefire.version>
</properties>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
<!-- testing -->
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-jetty</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
<configuration>
<parallel>methods</parallel>
<threadCount>10</threadCount>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
Example Jersey Rest Service
This jersey rest service is a simple example to explain the common HTTP Methods used like: GET, POST, PUT, DELETE. So we can properly show you how to unit test these services.
package com.memorynotfound.rs;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.List;
@Path("/notifications")
public class NotificationRestService {
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<Notification> fetchAll() {
// fetch all notifications
List<Notification> notifications = new ArrayList<Notification>();
notifications.add(new Notification(1, "New user created"));
notifications.add(new Notification(2, "New order created"));
return notifications;
}
@GET
@Path("{id: \\d+}")
@Produces(MediaType.APPLICATION_JSON)
public Notification fetchBy(@PathParam("id") int id) {
// fetch notification by id
return new Notification(id, "Rise and shine.");
}
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Notification create(Notification notification) {
// create notification
return notification;
}
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public void update(Notification notification) {
// update notification
}
@DELETE
@Path("{id: \\d+}")
@Produces(MediaType.APPLICATION_JSON)
public void delete(@PathParam("id") int id) {
// deleting notification
}
}
Notification DTO (Data Transfer Object) used for automatic marshalling and data retrieval.
package com.memorynotfound.rs;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Notification {
private Integer id;
private String message;
/**
* Default no-args constructor needed for jaxb
*/
public Notification() {
}
public Notification(Integer id, String message) {
this.id = id;
this.message = message;
}
public Integer getId() {
return id;
}
public String getMessage() {
return message;
}
}
Jersey application Configuration. This configures jersey so we don’t need a web.xml file.
package com.memorynotfound.rs;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("/api")
public class ApplicationConfig extends Application {
@Override
public Map<String, Object> getProperties() {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("jersey.config.server.provider.packages", "com.memorynotfound.rs");
return properties;
}
}
Test Jersey Rest Service with JUnit and Jersey
Testing with jersey Test Framework is relatively easy. You need to subclass org.glassfish.jersey.test.JerseyTest
and configure the resource and/or providers that need to be deployed in order to test our services. We need to override the JerseyTest#configure()
method to configure our application. In this example we return a ResourceConfig
. The ResourceConfig
is a sub-class of JAX-RS Application. It is a Jersey convenience class for configuring JAX-RS applications.
Finally we can write our JUnit tests. We obtain a WebTarget
by calling the JerseyTest#target(path)
method. It is on this target we can make a request, add parameters, headers, etc.. When the WebTarget
is invoked we simply investigate the response namely the status code returned by the service.
package com.memorynotfound.rs.test;
import com.memorynotfound.rs.Notification;
import com.memorynotfound.rs.NotificationRestService;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.junit.Test;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import static junit.framework.TestCase.assertNotNull;
import static org.junit.Assert.assertEquals;
public class NotificationRestServiceTest extends JerseyTest {
@Override
public Application configure() {
enable(TestProperties.LOG_TRAFFIC);
enable(TestProperties.DUMP_ENTITY);
return new ResourceConfig(NotificationRestService.class);
}
@Test
public void testFetchAll() {
Response output = target("/notifications").request().get();
assertEquals("should return status 200", 200, output.getStatus());
assertNotNull("Should return list", output.getEntity());
}
@Test
public void testFetchBy(){
Response output = target("/notifications/1").request().get();
assertEquals("Should return status 200", 200, output.getStatus());
assertNotNull("Should return notification", output.getEntity());
}
@Test
public void testFetchByFail_DoesNotHaveDigit(){
Response output = target("/notifications/no-id-digit").request().get();
assertEquals("Should return status 404", 404, output.getStatus());
}
@Test
public void testCreate(){
Notification notification = new Notification(null, "Invoice was deleted");
Response output = target("/notifications")
.request()
.post(Entity.entity(notification, MediaType.APPLICATION_JSON));
assertEquals("Should return status 200", 200, output.getStatus());
assertNotNull("Should return notification", output.getEntity());
}
@Test
public void testUpdate(){
Notification notification = new Notification(1, "New user created at Antwerp");
Response output = target("/notifications")
.request()
.put(Entity.entity(notification, MediaType.APPLICATION_JSON));
assertEquals("Should return status 204", 204, output.getStatus());
}
@Test
public void testDelete(){
Response output = target("/notifications/1").request().delete();
assertEquals("Should return status 204", 204, output.getStatus());
}
}
great job !!