package yeti.jaxrs.jersey; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.sameInstance; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import org.junit.Test; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Scope; import com.google.inject.Scopes; import com.google.inject.Stage; import com.sun.jersey.api.core.DefaultResourceConfig; import com.sun.jersey.api.core.HttpContext; import com.sun.jersey.api.core.ResourceConfig; import com.sun.jersey.api.model.AbstractResource; import com.sun.jersey.core.spi.component.ioc.IoCComponentProviderFactory; import com.sun.jersey.guice.spi.container.GuiceComponentProviderFactory; import com.sun.jersey.server.impl.component.IoCResourceFactory; import com.sun.jersey.server.impl.component.ResourceFactory; import com.sun.jersey.server.impl.inject.ServerInjectableProviderFactory; import com.sun.jersey.server.spi.component.ResourceComponentProvider; public class GuiceComponentProviderFactoryTest { public static class BoundInParentInjector { @Inject public BoundInParentInjector() {} } public static class BoundInChildInjector { @Inject public BoundInChildInjector(BoundInParentInjector fromParentInjector) {} } private ResourceFactory buildResourceFactory(Injector injector) { ResourceConfig resourceConfig = new DefaultResourceConfig(); IoCComponentProviderFactory componentProviderFactory = new GuiceComponentProviderFactory(resourceConfig, injector); return new IoCResourceFactory(resourceConfig, new ServerInjectableProviderFactory(), Arrays.asList(componentProviderFactory)); } private Injector withExplicitBindingFor(final Scope scope) { Injector parentInjector = Guice.createInjector(Stage.PRODUCTION, new AbstractModule(){ @Override protected void configure() { bind(BoundInParentInjector.class).in(scope); } }); Injector childInjector = parentInjector.createChildInjector(new AbstractModule(){ @Override protected void configure() { bind(BoundInChildInjector.class).in(scope); } }); return childInjector; } @Test public void shouldRespectNoScopedExplicitBindingInParentInjectorAsPerRequestComponentScope() throws Exception { ResourceComponentProvider componentProvider1 = buildResourceFactory(withExplicitBindingFor(Scopes.NO_SCOPE)).getComponentProvider(BoundInParentInjector.class); componentProvider1.init(new AbstractResource(BoundInParentInjector.class)); Map requestContext1 = new HashMap(); HttpContext request1 = mock(HttpContext.class); when(request1.getProperties()).thenReturn(requestContext1); assertThat(componentProvider1.getInstance(request1), sameInstance(componentProvider1.getInstance(request1))); ResourceComponentProvider componentProvider2 = buildResourceFactory(withExplicitBindingFor(Scopes.NO_SCOPE)).getComponentProvider(BoundInParentInjector.class); componentProvider2.init(new AbstractResource(BoundInParentInjector.class)); Map requestContext2 = new HashMap(); HttpContext request2 = mock(HttpContext.class); when(request2.getProperties()).thenReturn(requestContext2); assertThat(componentProvider1.getInstance(request1), not(sameInstance(componentProvider2.getInstance(request2)))); } @Test public void shouldRespectNoScopedExplicitBindingInChildInjectorAsPerRequestComponentScope() throws Exception { ResourceComponentProvider componentProvider1 = buildResourceFactory(withExplicitBindingFor(Scopes.NO_SCOPE)).getComponentProvider(BoundInChildInjector.class); componentProvider1.init(new AbstractResource(BoundInChildInjector.class)); Map requestContext1 = new HashMap(); HttpContext request1 = mock(HttpContext.class); when(request1.getProperties()).thenReturn(requestContext1); assertThat(componentProvider1.getInstance(request1), sameInstance(componentProvider1.getInstance(request1))); ResourceComponentProvider componentProvider2 = buildResourceFactory(withExplicitBindingFor(Scopes.NO_SCOPE)).getComponentProvider(BoundInChildInjector.class); componentProvider2.init(new AbstractResource(BoundInChildInjector.class)); Map requestContext2 = new HashMap(); HttpContext request2 = mock(HttpContext.class); when(request2.getProperties()).thenReturn(requestContext2); assertThat(componentProvider1.getInstance(request1), not(sameInstance(componentProvider2.getInstance(request2)))); } @Test public void shouldRespectSingletonScopedExplicitBindingInParentInjectorAsSingletonComponentScope() throws Exception { ResourceComponentProvider componentProvider1 = buildResourceFactory(withExplicitBindingFor(Scopes.SINGLETON)).getComponentProvider(BoundInParentInjector.class); componentProvider1.init(new AbstractResource(BoundInParentInjector.class)); Map requestContext1 = new HashMap(); HttpContext request1 = mock(HttpContext.class); when(request1.getProperties()).thenReturn(requestContext1); assertThat(componentProvider1.getInstance(request1), sameInstance(componentProvider1.getInstance(request1))); ResourceComponentProvider componentProvider2 = buildResourceFactory(withExplicitBindingFor(Scopes.SINGLETON)).getComponentProvider(BoundInParentInjector.class); componentProvider2.init(new AbstractResource(BoundInParentInjector.class)); Map requestContext2 = new HashMap(); HttpContext request2 = mock(HttpContext.class); when(request2.getProperties()).thenReturn(requestContext2); assertThat(componentProvider2.getInstance(request1), sameInstance(componentProvider2.getInstance(request2))); } @Test public void shouldRespectSingletonScopedExplicitBindingInChildInjectorAsSingletonComponentScope() throws Exception { ResourceComponentProvider componentProvider1 = buildResourceFactory(withExplicitBindingFor(Scopes.SINGLETON)).getComponentProvider(BoundInChildInjector.class); componentProvider1.init(new AbstractResource(BoundInChildInjector.class)); Map requestContext1 = new HashMap(); HttpContext request1 = mock(HttpContext.class); when(request1.getProperties()).thenReturn(requestContext1); assertThat(componentProvider1.getInstance(request1), sameInstance(componentProvider1.getInstance(request1))); ResourceComponentProvider componentProvider2 = buildResourceFactory(withExplicitBindingFor(Scopes.SINGLETON)).getComponentProvider(BoundInChildInjector.class); componentProvider2.init(new AbstractResource(BoundInChildInjector.class)); Map requestContext2 = new HashMap(); HttpContext request2 = mock(HttpContext.class); when(request2.getProperties()).thenReturn(requestContext2); assertThat(componentProvider2.getInstance(request1), sameInstance(componentProvider2.getInstance(request2))); } }