I have a resource endpoint that injects a @PathParam into constructor, i.e., different instance per @PathParam value. It all works fine in Jetty. But now I'm trying to write unit tests using Jersey Test Framework, and it seems that the test framework only supports one registered endpoint per type.
So if I do something like this:
@Path("/users")
public class MyResource {
public MyResource(@PathParam("userId") int userId) {
}
@Path("{userId}")
public String get() {
}
}
public class MyTest extends JerseyTestNg.ContainerPerClassTest {
@Override
protected Application configure() {
return new ResourceConfig()
.register(new MyResource(1))
.register(new MyResource(2));
}
@Test
public void test2() {
target("/users/1").request().get();
}
@Test
public void test2() {
target("/users/2").request().get();
}
}
I see that both test1 and test2 are invoking the instance of MyResource(1). Is this expected? Is there a solution to invoke the correct instance?
You should register the resource as a class. Jersey will create it for you. And handle all the injections.
"The example I posted is dumbed down. In reality, my resource constructor has another injected object that I need to mock. So how would I specify a mocked object parameter for the constructor?"
You can do something like
@Mock
private Service service;
@Override
public ResourceConfig configure() {
MockitoAnnotations.initMocks(this);
return new ResourceConfig()
.register(MyResource.class)
.register(new AbstractBinder() {
@Override
protected configure() {
bind(service).to(Service.class);
}
});
}
@Test
public void test() {
when(service.getSomething()).thenReturn("Something");
// test
}
Assuming you are already using the built in HK2 DI, and have an @Inject
annotation on the constructor of your resource class, this should work. In the AbstractBinder
we are making the mock object injectable. So now Jersey can inject it into your resource.
See Also: