Domanda

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

È stato utile?

Soluzione

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top