0

I am working on a REST project implemented with Jersey 2 (for REST API) and Spring (for DI), and I want to write functional/integration tests. I tried to use JerseyTest framework and to use real database for those tests. Only thing that I have in my mind to mock are remote Web Services (SOAP) that my app consumes, for which I should mock generated WS clients.

After a lot of time spent on investigations about JerseyTest framework with Jersey2 and Spring it seems it is not possible to have that setup for integration tests. Can you tell me did you succeeded to setup something similar?

Problems with JerseyTest is AFAIK that I can not use all settings from web.xml config file, like registering multiple filters and servlets, and also that I can not use the same Spring context that I configured for app that runs under tests for defining mock objects and what they return per test. Each my REST resource is under Spring Security protection, it is also not loaded with JerseyTest framework because of the need to register it's listener.

Please give some advices how to achieve that or maybe to use another testing framework in order to achieve all this mentioned...

Here is my code from that junit test:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {MyResourceTest.MOCK_SPRING_APPLICATION_CONTEXT})
public class MyResourceTest extends JerseyTest {

    public static final String MOCK_SPRING_APPLICATION_CONTEXT = "classpath:spring/testApplicationContext.xml";

    @Override
    protected Application configure() {
        ResourceConfig resourceConfig = new MyResourceConfig();
        disable(TestProperties.LOG_TRAFFIC);
        disable(TestProperties.DUMP_ENTITY);
        resourceConfig.property("contextConfigLocation", MOCK_SPRING_APPLICATION_CONTEXT);
        return resourceConfig;
    }

    @Override
    protected TestContainerFactory getTestContainerFactory() {
        return new GrizzlyWebTestContainerFactory();
    }

    @Override
    protected DeploymentContext configureDeployment() {
        return ServletDeploymentContext
                .forServlet(new ServletContainer(new MyResourceConfig()))
                .addListener(MyContextLoaderListener.class) // Extends Spring's listener
                .addListener(RequestContextListener.class)
                .contextParam("contextConfigLocation", MOCK_SPRING_APPLICATION_CONTEXT)
                .build();
    }

    @Test
    @SqlGroup({
            @Sql(scripts = {"classpath:db_scripts/clean-up.sql", "classpath:db_scripts/init-db.sql"}),
            @Sql(scripts = "classpath:db_scripts/clean-up.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
    })
    public void shouldReceiveResourceTest() throws IOException {
        // Prepare request ...
        final MyResponse myResponse = target("/resource/1").request().post(myRequest, MyResponse.class);
        assertNotNull(myResponse);
    }

}
HomerJ
  • 1
  • 1
  • 2
  • I solved this by adding Spring Boot and using it's Integration tests support. I just followed this example [link](https://github.com/kolorobot/spring-boot-jersey-demo) – HomerJ Nov 14 '15 at 21:59

2 Answers2

0

Maybe my solution example can solve your problem. I hosted it on GitHub:

The better way to integrate JerseyTest with Spring

  • No inheritance from JerseyTest in junit test class
  • No dependencies on Jersey in junit test class, just pure jax-rs dependency
  • perfectly integrate SpringJUnit4ClassRunner and @ContextConfiguration
RJ.Hwang
  • 1,683
  • 14
  • 24
0

You have already fallback to Spring Boot option but, let me share with you how I have managed to get the integration testing working without Spring Boot.

The most tricky part is registering the content of your web.xml and in order to do that you need to setup your server as follow

  1. Use @Before with an if condition to make sure that your container is setup once for the entire test class, that way spring doesn't have to autowire beans for every test
  2. Programmatically create A WebappContext and register all that is inside your web.xml and then use it's deploy method to pass it A server instance (i.e. Grizzly, etc.)

How is it done?

@Before
public void setUp() throws Exception {
    if (server == null) {
        final ResourceConfig rc = new ResourceConfig(A.class, B.class);

        WebappContext ctx = new WebappContext() {};
        ctx.addContextInitParameter("contextConfigLocation", "classpath:applicationContext.xml");

        ctx.addListener("com.package.something.AServletContextListener");

        server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
            ctx.deploy(server);
        }
    }

In my web.xml I had overrided ContextListener hence the following line

ctx.addListener("..."); 

In similar fashion you can programmatically create a WebappContext which is nothing but, your web.xml. It works like a charm.

I have answered a similar questions, here is the link to the answer if you want to know in more detail.

Community
  • 1
  • 1
Raf
  • 7,505
  • 1
  • 42
  • 59