# Jersey Test Framework

This chapter will present how to write tests for your resources using Jersey Test Framework and how to run them in various containers. Additionally it will explain how to create new module for not yet supported container.

Jersey currently provides following modules:

- jersey-test-framework-grizzly
- jersey-test-framework-grizzly2
- jersey-test-framework-http
- jersey-test-framework-inmemory
- jersey-test-framework-embedded-glassfish
- jersey-test-framework-external

## What is different in Jersey 1.2

There are some significant breaking changes in Jersey 1.2. In prior Jersey versions users were able to select container factory just by specifying it in some property. That was convenient from user perspective but not good from build perspective. Former test framework artifact was dependent on all containers which is useless in most cases (usually you test only with one container).

Solution to this is modularization - make module for each test container. It has one drawback: users will have to have other dependency in their applications, for example if you want to test on embedded grizzly container, you will declare (only) dependency on jersey test framework grizzly module. You can declare multiple test containers this way and select one by defining property `jersey.test.containerFactory`.

Another change (non-breaking) is renaming Jersey parameters which control container factory, used port and host name for external container. Old properties are still working but users are encouraged to use new ones.

Property name changes

Prior Jersey 1.2 | Jersey 1.2+
--- | ---
test.containerFactory | jersey.test.containerFactory
JERSEY_HTTP_PORT | jersey.test.port
JERSEY_HOST_NAME (used with external container) | jersey.test.host

## Using test framework

When you want test your resources in maven-based project, you need to add dependency on one of the Jersey Test Framework modules. You can take a look at helloworld sample pom file. There is declared dependency on:

                    <dependency>
                    <groupId>com.sun.jersey.jersey-test-framework</groupId>
                    <artifactId>jersey-test-framework-grizzly2</artifactId>
                    <version>${project.version}</version>
                    <scope>test</scope>
                    </dependency>

which means that Grizzly Web container (version 2.x) will be used for testing.

You can specify more than one module in dependencies and choose which module will be used by `jersey.test.containerFactory` property. Every module should contain at least one container factory.

jersey-test-framework-grizzly

  `com.sun.jersey.test.framework.spi.container.grizzly.web.GrizzlyWebTestContainerFactory` `com.sun.jersey.test.framework.spi.container.grizzly.GrizzlyTestContainerFactory`

jersey-test-framework-grizzly2

  `com.sun.jersey.test.framework.spi.container.grizzly2.web.GrizzlyWebTestContainerFactory` `com.sun.jersey.test.framework.spi.container.grizzly2.GrizzlyTestContainerFactory`

jersey-test-framework-http

  `com.sun.jersey.test.framework.spi.container.http.HTTPContainerFactory`

jersey-test-framework-inmemory

  `com.sun.jersey.test.framework.spi.container.inmemory.InMemoryTestContainerFactory`

jersey-test-framework-embedded-glassfish

  `com.sun.jersey.test.framework.spi.container.embedded.glassfish.EmbeddedGlassFishTestContainerFactory`

jersey-test-framework-external

  `com.sun.jersey.test.framework.spi.container.external.ExternalTestContainerFactory`

Basically you can just add dependency on single module and its container factory would be used. Problem is when you specify module which has more than one container factory or multiple modules. If this happen, test framework will choose factory using following rules:

    if("jersey.test.containerFactory" not specified)
        look for factories
        if(factories.count == 1)
            use found factory
        else
            if(com.sun.jersey.test.framework.spi.container.grizzly2.web.GrizzlyWebTestContainerFactory is present)
                use it // current default jersey test container factory
            else
                use first found and log warning
    else
        use factory class specified in "jersey.test.containerFactory"

That means if your project depends on multiple test framework modules and you want to control which will be used, you have to declare which one in property called "jersey.test.containerFactory", for example like this: `mvn clean install -Djersey.test.containerFactory=com.sun.jersey.test.framework.spi.container.inmemory.InMemoryTestContainerFactory`

## Creating tests

Jersey Test Framework uses JUnit version 4.X, so if you can write standard unit tests, you can easily create Jersey Test. You need to declare test as a descendant of JerseyTest class.

    public class MainTest extends JerseyTest {

        public MainTest()throws Exception {
            super("com.sun.jersey.samples.helloworld.resources");
        }

        @Test
        public void testHelloWorld() {
            WebResource webResource = resource();
            String responseMsg = webResource.path("helloworld").get(String.class);
            assertEquals("Hello World", responseMsg);
        }

    }

Note `super` call in constructor - it passes list of package names to scan (it really is a list, JerseyTest constructor has variable argument count). Another useful method is `resource()` which returns WebResource instance with URI set to base URI of your application. You can get preconfigured Jersey Client instance similarly by calling `client()` method.

## Creating own module

Creating your own module is pretty straightforward, you just have to implement `com.sun.jersey.test.framework.spi.container.TestContainerFactory` and `com.sun.jersey.test.framework.spi.container.TestContainer`. TestContainer factory is there basically for returning TestContainer instance and TestContainer has self-explanatory methods: `start()`, `stop()`, `getClient()` and `getBaseURI()`. I recommend taking look at source code and read javadoc of these two classes, all you need is there.

You should be avare of another thing when implementing own jersey test framework module. If you want it to be usable by running just `mvn clean install` (when only your module is specified), you need to add META-INF/services/com.sun.jersey.test.framework.spi.container.TestContainerFactory file into your jar and put there your factory class (fully classified) name.

## Running tests outside Maven

Since Jersey is Maven based project, executing tests without Maven can be painful. You have to have everything needed present on classpath and by everything is meant following list:

- jersey-server
- jersey-core
- jsr311-api
- jersey-test-framework-grizzly
- jersey-test-framework-core
- jersey-client
- javax.servlet
- junit
- jaxb-impl
- jaxb-api
- stax-api
- activation
- grizzly-servlet-webserver
- grizzly-http
- grizzly-framework
- grizzly-utils
- grizzly-rcm
- grizzly-portunif
- grizzly-http-servlet
- servlet-api

This is needed to run `helloworld` sample tests, if you want run something more complex or with different test container (grizzly is used here), you may need to add other application specific dependencies (and remove some as well).

As was already written above, Jersey test is descendant of standard unit test so it can be run same way. You can execute it by executing `org.junit.runner.JUnitCore` and passing your test class name as parameter, from ant (junit-task) or whatever you are used to.