javajerseyguicejersey-2.0guice-3

How to unit test Jersey + Guice: ServiceLocator?


By using HK2's guice-bridge I managed to integrate Jersey 2.x with Guice 3.x.

public class MyApp extends ResourceConfig {

    @Inject
    public MyApp(ServiceLocator serviceLocator) {
        packages("com.mycompany");

        ...

        GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
        GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
        guiceBridge.bridgeGuiceInjector(GuiceContext.INJECTOR);
    }
}

But now my Jersey tests don't work anymore.

public abstract class AbstractJerseyTest extends JerseyTest {

    public AbstractJerseyTest() throws TestContainerException {
        super(new InMemoryTestContainerFactory());
    }

    protected Application configure() {
        new MyApp(); // ERROR: missing 'ServiceLocator'
    }

}

So where do I get a ServiceLocator for my unit tests?


Solution

  • We made it work with the help of Groovy:

    public class MemoryTestContainerFactory implements TestContainerFactory {
    
        private final Class<? extends Application> jaxrsApplicationClass;
    
        public MemoryTestContainerFactory(Class<? extends Application> jaxrsApplicationClass) {
            this.jaxrsApplicationClass = jaxrsApplicationClass;
        }
    
        @Override
        public TestContainer create(URI baseUri, DeploymentContext context) throws IllegalArgumentException {
            return new MemoryTestContainer(jaxrsApplicationClass, baseUri, context);
        }
    
        private static class MemoryTestContainer implements TestContainer {
    
            private final URI baseUri;
            private final ApplicationHandler appHandler;
            private final AtomicBoolean started = new AtomicBoolean(false);
    
            private static final Logger LOGGER = Logger.getLogger(MemoryTestContainer.class.getName());
    
            MemoryTestContainer(Class<? extends Application> jaxrsApplicationClass, URI baseUri, DeploymentContext context) {
                this.baseUri = UriBuilder.fromUri(baseUri).path(context.getContextPath()).build();    
                this.appHandler = new ApplicationHandler(jaxrsApplicationClass);
            }
    
            @Override
            public ClientConfig getClientConfig() {
                def provider = new InMemoryConnector.Provider(baseUri, appHandler) // private access (only works with Groovy)
                return new ClientConfig().connectorProvider(provider);
            }
    
            @Override
            public URI getBaseUri() {
                return baseUri;
            }
    
            @Override
            public void start() {
                if (started.compareAndSet(false, true)) {
                    LOGGER.log(Level.FINE, "Starting InMemoryContainer...");
                } else {
                    LOGGER.log(Level.WARNING, "Ignoring start request - InMemoryTestContainer is already started.");
                }
            }
    
            @Override
            public void stop() {
                if (started.compareAndSet(true, false)) {
                    LOGGER.log(Level.FINE, "Stopping InMemoryContainer...");
                } else {
                    LOGGER.log(Level.WARNING, "Ignoring stop request - InMemoryTestContainer is already stopped.");
                }
            }
        }
    }
    

    It's not pretty, but it works.