Unit & Integration Testing REST Services

Add Integration Tests

Writing the integration test code proved simpler than the unit tests, but getting them running wasn’t.

First, let’s look at the tests. They are implemented using restfuse (a JUnit extension for automated REST service testing).

One other small item to highlight is the regular expression Hamcrest matcher; the static import here being nothing more than a builder wrapper for Piotr Gabryanczyk’s implementation.

package com.nigeleke.restin.service;

import com.eclipsesource.restfuse.Destination;
import com.eclipsesource.restfuse.HttpJUnitRunner;
import com.eclipsesource.restfuse.MediaType;
import com.eclipsesource.restfuse.Method;
import com.eclipsesource.restfuse.Response;
import com.eclipsesource.restfuse.annotation.Context;
import com.eclipsesource.restfuse.annotation.HttpTest;
import java.util.List;
import javax.ws.rs.core.HttpHeaders;
import org.junit.Rule;
import org.junit.runner.RunWith;

import static com.eclipsesource.restfuse.Assert.*;
import static com.nigeleke.tuttle.hamcrest.Matchers.*;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

@RunWith(HttpJUnitRunner.class)
public class AnEntityFacadeRESTIT {

  @Rule
  public Destination destination = new Destination(this, "http://localhost:21957/restin/rest");

  @Context
  private Response response;
  @HttpTest(method = Method.POST, path = "/anentity", type = MediaType.APPLICATION_JSON, content = "{ \"name\":\"Arthur C Clarke\" }")
  public void testCreateJson() throws Exception {
    assertCreated(response);

    assertThat(response.getType(), equalTo(MediaType.APPLICATION_JSON));
    assertThat(response.getBody(), matchesRegex("^\\{\\\"id\\\":\\d+,\\\"name\\\":\\\"Arthur C Clarke\\\"}$"));
    assertThat(response.getUrl(), matchesRegex("^http://localhost:21957/restin/rest/anentity$"));

    List<String> contentLocations = response.getHeaders().get(HttpHeaders.CONTENT_LOCATION);
    assertNotNull(contentLocations);
    assertEquals(1, contentLocations.size());
    assertThat(contentLocations.iterator().next(), matchesRegex("^http://localhost:21957/restin/rest/anentity/\\d+$"));
  }
}

Embedded Glassfish was used as the test container, along with Embedded Derby for the test database.

The “more interesting” changes were in the pom.xml. In addition to the restfuse dependency already stated, the embedded Glassfish maven plugin was incorporated, along with a Derby server plugin.

First, the pom.xml additions for Glassfish were:

<plugin>
  <groupId>org.glassfish.embedded</groupId>
  <artifactId>maven-embedded-glassfish-plugin</artifactId>
  <version>4.0</version>
  <configuration>
    <name>${project.artifactId}</name>
    <app>${project.build.directory}/${project.artifactId}-${project.version}.war</app>
    <autoDelete>true</autoDelete>
    <ports>
      <http-listener>21957</http-listener>
      <https-listener>21954</https-listener>
    </ports>
    <commands>
      <command>add-resources ${basedir}/src/test/setup/glassfish-resources.xml</command>
    </commands>
    <deploymentParams>
      <param>--contextroot=/${project.artifactId}</param>
      <param>--createtables=false</param>
      <param>--precompilejsp=false</param>
    </deploymentParams>
  </configuration>
  <executions>
    <execution>
      <id>start-container</id>
      <phase>pre-integration-test</phase>
      <goals>
        <goal>start</goal>
        <goal>admin</goal>
        <goal>deploy</goal>
      </goals>
    </execution>
    <execution>
      <id>stop-container</id>
      <phase>post-integration-test</phase>
      <goals>
        <goal>undeploy</goal>
        <goal>stop</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Notice the command add-resources. This sets up the test JNDI reference to an embedded derby database.

Before using add-resources I was getting an error message for a defaulted persistence unit name restin__pm. There are many posts around this exception, but the solutions weren’t working for me. The glassfish-resources solution was the solution that finally worked – and hence the reason for sharing this on the post.

The resource glassfish-resources.xml is placed under the test resources folder and contains:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
  <jdbc-connection-pool name="derby_net_restin_APPPool"
    datasource-classname="org.apache.derby.jdbc.EmbeddedDataSource"
    res-type="javax.sql.DataSource" ping="true">
    <property name="databaseName" value="memory:restin" />
    <property name="connectionAttributes" value=";create=true" />
    <property name="user" value="APP" />
    <property name="password" value="APP" />
    <property name="driverClass" value="org.apache.derby.jdbc.EmbeddedDriver" />
  </jdbc-connection-pool>
  <jdbc-resource jndi-name="restin" pool-name="derby_net_restin_APPPool" object-type="user" enabled="true" />
</resources>

Back to the pom.xml, and the Derby servers is started and stopped with:

<plugin>
  <groupId>org.carlspring.maven</groupId>
  <artifactId>derby-maven-plugin</artifactId>
  <version>1.7</version>
  <configuration>
    <connectionURL>jdbc:derby:memory:restin</connectionURL>
  </configuration>
  <executions>
    <execution>
      <id>start-derby</id>
      <phase>pre-integration-test</phase>
      <goals>
        <goal>start</goal>
      </goals>
    </execution>
    <execution>
      <id>stop-derby</id>
      <phase>post-integration-test</phase>
      <goals>
        <goal>stop</goal>
      </goals>
    </execution>
  </executions>
</plugin>

The MAVEN_OPTS environment variable needed to be set to get the integration tests to run successfylly.

export MAVEN_OPTS="-Xmx512m -XX:MaxPermSize=128m"

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.