How to in-memory unit test Spring-Jersey
A few things I would fix:
You are using Jersey 1.x flavored Jersey Test Framework, but your app is Jersey 2.x. See below for 2.x dependency.
I've never used the Jersey 1.x flavored Test Framework, but with Jersey 2.x, the In-Memory container doesn't support servlet dependent features. See below for different dependency.
With Jersey Test Framework, you do not need to create the
Client
yourself. There is one created, and we can simple callJerseyTest
'starget(String path)
method to get back aWebTarget
(Jersey 2.x,WebResource
is Jersey 1.x)
Here is a refactor that works.
Dependency (I only added this dependency, and didn't take anything out, as your GitHub project didn't include anything test related, as your code example above does)
<dependency> <groupId>org.glassfish.jersey.test-framework.providers</groupId> <artifactId>jersey-test-framework-provider-grizzly2</artifactId> <version>2.15</version></dependency>
Test
import com.component.ResourceRegister;import org.glassfish.jersey.servlet.ServletContainer;import org.glassfish.jersey.test.DeploymentContext;import org.glassfish.jersey.test.JerseyTest;import org.glassfish.jersey.test.ServletDeploymentContext;import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;import org.glassfish.jersey.test.spi.TestContainerFactory;import org.junit.Assert;import org.junit.Test;import org.springframework.web.context.ContextLoaderListener;public class SpringTest extends JerseyTest { @Override protected TestContainerFactory getTestContainerFactory() { return new GrizzlyWebTestContainerFactory(); } @Override protected DeploymentContext configureDeployment(){ return ServletDeploymentContext .forServlet(new ServletContainer(new ResourceRegister())) .addListener(ContextLoaderListener.class) .contextParam("contextConfigLocation", "classpath:applicationContext.xml") .build(); } @Test public void test() { String response = target("test").request().get(String.class); Assert.assertEquals("Hello", response); System.out.println(response); } }
For those not use an xml context file, you can use an annotation config application context, and add it as an init param
return ServletDeploymentContext .forServlet(new ServletContainer(new ResourceRegister())) .addListener(ContextLoaderListener.class) .initParam("contextConfig", new AnnotationConfigApplicationContext(YourSpringConfig.class)) .build();
Other Resources:
- Jersey Test Framework Documentation
- More examples from Test Framework source code tests. (Hint: the link I provided is for grizzly web container examples, but if you traverse back to providers, you can look at each provider and go to the test packages for examples for those providers)
UPDATE
So after a few more test, here are a couple interesting things I discovered
One:
With the above dependency, even if we don't configure the DeploymentContext
, and just override Application configure()
in the JerseyTest
, it will still work. Can't really explain it, but it appears the descriptor is still picked up.
import javax.ws.rs.core.Application;import org.glassfish.jersey.server.ResourceConfig;import org.glassfish.jersey.test.JerseyTest;import org.junit.Assert;import org.junit.Test;public class SpringTest extends JerseyTest { @Override public Application configure() { return new ResourceConfig().packages("com.controller"); } @Test public void test() { String response = target("test").request().get(String.class); Assert.assertEquals("Hello", response); System.out.println(response); } }
Two:
Even if we get rid of the above dependency (grizzly) and use the in-memory dependency, the same simple previous test works. The documentation states
In-Memory container is not a real container. It starts Jersey application and directly calls internal APIs to handle request created by client provided by test framework. There is no network communication involved. This containers does not support servlet and other container dependent features, but it is a perfect choice for simple unit tests.
So I am not completely sure what Servlet features they are referring to, as this test still works
<dependency> <groupId>org.glassfish.jersey.test-framework.providers</groupId> <artifactId>jersey-test-framework-provider-inmemory</artifactId> <version>2.15</version></dependency>
What I don't understand in particular, is this statement
"There is no network communication involved"
because when I run the test, I see a log
INFO: Creating InMemoryTestContainer configured at the base URI http://localhost:9998/