I’m trying to write some unit tests for a gwt-dispatch service with JUnit. I’m getting the following error when stepping through the test with my debugger:
Error in custom provider, com.google.inject.OutOfScopeException: Cannot access scoped object. Either we are not currently inside an HTTP Servlet request, or you may have forgotten to apply com.google.inject.servlet.GuiceFilter as a servlet filter for this request.
I’m going to simplify the code a bit here — hopefully I’m not stripping out anything necessary.
import junit.framework.TestCase;
import net.customware.gwt.dispatch.client.standard.StandardDispatchService;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.ServletModule;
...
public class LoggedInServiceTest extends TestCase {
Injector i;
StandardDispatchService service;
protected com.google.inject.Injector getInjector() {
return Guice.createInjector(new ServletModule(),
new TestServletModule(),
new ActionsHandlerModule(),
new TestDispatchModule(),
new OpenIdGuiceModule());
}
public void setUp() throws Exception {
i = getInjector();
service = i.getInstance(StandardDispatchService.class);
}
public void testNotLoggedIn() {
try {
GetProjectsResult result = (GetProjectsResult) service.execute(new GetProjectsAction());
result.getSizeOfResult();
} catch (Exception e) {
fail();
}
}
}
The service request is indeed supposed to be going through a GuiceFilter, and it looks like that filter is not being set.
Any ideas on what other setup needs to be done to register the filter?
The problem is just what it states. You are trying to access a scoped object, but you are not currently in the scope. Most likely, your test is asking the injector for a
RequestScopedobject or an object that has aRequestScopedobject in the injection dependency tree, but the test didn’t do anything to enter the scope.Binding the
GuiceFilterin the test doesn’t help, because your test isn’t trying to send anHttpServletRequestthroughGuiceFilterto a servlet.The best option would be to unit test your code. Create your classes in isolation, injecting mocks.
Assuming you want to do some kind of integration test, you have three options:
bindScope(RequestScoped.class, new FakeScope). TheFakeScopeclass would implementScopeand have methods to enter and exit the scope. You may have to “seed” the scope with fake implementations of objects you depend on. See the Guice CustomScopes wiki page. This is the best option for integration tests, IMHOServletScopes.scopeRequest(Javadoc) to run part of the test code inside of a simulated request scope. This gets a bit ugly since you need to pass aCallable.Things might get a bit messy if the class you are testing depends indirectly on
HttpServletRequestorHttpServletResponse. These classes can be challenging to setup correctly. Most of your classes should not depend on the servlet classes directly or indirectly. If that is not the case, you are either doing something wrong or you need to find a good action framework that allows you have most of your code not depend on these classes.Here’s an example of approach 1, using
SimpleScopefrom the Guice CustomScopes wiki page: