Pergunta

I'm trying to use google guice for dependency injection however I can't seem to wire everything togheter.

In my web.xml I defined the guiceFilter and the guiceListener like so:

   <filter>
    <filter-name>guiceFilter</filter-name>
    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>guiceFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<listener>
    <listener-class>backend.listener.GuiceConfigListener</listener-class>
</listener>

the config listener is basicly pretty simple:

@Override
protected Injector getInjector(){
    return Guice.createInjector(new ServletModule(), new ArtsModule());
}

and the ArtsModule at this moment just has one binding like so:

@Override
protected void configure(){
    bind(ArtsDAO.class).to(ArtsDAOGae.class);
}

I then continue to do a field injection of the ArtsDao in a service class:

@Inject
private ArtsDAO artsDAO;

But when I try to build my project (which is a maven build) I get a NPE on the artsDAO field, this most likely happens because the unit tests aren't running in a web environment.

Can anyone advice me on how to configure the guice bidings so that they are picked up during unit testing?

Thanks

Foi útil?

Solução

Pip,

this is not trivial task but definitely you can achieve what you want.

First of all have a look at Tadedon project at https://code.google.com/p/tadedon especially tadedon-guice-servlet-mock.

You will need something like fake container for your test. My fake container contains also Apache Shiro integration so you can throw it out, It looks like:

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.xemantic.tadedon.guice.servlet.mock.FakeServletContainer;
import com.xemantic.tadedon.guice.servlet.mock.FakeServletContainerModule;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.SubjectThreadState;
import org.apache.shiro.web.subject.WebSubject;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;

import javax.servlet.ServletException;
import java.io.IOException;
import java.util.Arrays;
public class FakeTestContainerInit {

    private final FakeServletContainer servletContainer;
    private final Injector internalInjector;
    private Subject internalSubject;

    public FakeTestContainerInit() {
        this(new Module[] {});
    }

    public FakeTestContainerInit(Module... modules) {
        super();

        modules = Arrays.copyOf(modules, modules.length + 1);
        modules[modules.length-1] = new FakeServletContainerModule();
        internalInjector = Guice.createInjector(modules);
        servletContainer = internalInjector.getInstance(FakeServletContainer.class);
    }

    public void start() throws ServletException, IOException {
        this.start(true);
    }

    public void start(boolean initializeSecurityContext) throws ServletException, IOException {

        getServletContainer().start();

        MockHttpServletRequest request = servletContainer.newRequest("GET","/");
        MockHttpServletResponse response = new MockHttpServletResponse();

        if(initializeSecurityContext) {
            SecurityManager scm = internalInjector.getInstance(SecurityManager.class);
            internalSubject = new WebSubject.Builder(scm, request, response).buildWebSubject();
            SubjectThreadState sts = new SubjectThreadState(internalSubject);
            sts.bind();
        } else { internalSubject = null; }

        getServletContainer().service(request, response);

    }

    public void stop() {
        servletContainer.stop();
    }

    public FakeServletContainer getServletContainer() {
        return servletContainer;
    }

    public <T> T getInstance(final Class<T> type) throws IOException, ServletException {
        return getServletContainer().getInstance(type);
    }

    public <T> T getInstance(final Key<T> key) throws IOException, ServletException {
        return getServletContainer().getInstance(key);
    }

    public Subject getSubject() {
        return internalSubject;
    }
}

Dependencies:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
    </dependency>
    <dependency>
        <groupId>org.sonatype.sisu</groupId>
        <artifactId>sisu-guice</artifactId>
    </dependency>
    <dependency>
        <groupId>com.xemantic.tadedon</groupId>
        <artifactId>tadedon-guice-servlet-mock</artifactId>
    </dependency>

and Apache Shiro you won't need:

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-web</artifactId>
    </dependency>

All you need to do, is create FakeTestContainerInit and call start() and stop() method. Also all object creations have to be done via FakeTestContainerInit.getInstance method inside tests.

Well, I used it to test Vaadin application so I did not need sending requests and checking responses. So, this one you will need to implement. It can be done via getServletContainer().service(request, response);. But i think you will figure out. Hope it will help you.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top