Java 单元测试gwt调度
我正试图用JUnit为gwt调度服务编写一些单元测试。使用调试器单步执行测试时出现以下错误: 自定义提供程序com.google.inject.OutOfScopeException中出错:无法访问作用域对象。我们当前没有在HTTP Servlet请求中,或者您可能忘记将com.google.inject.Servlet.GuiceFilter应用为该请求的Servlet筛选器 我将在这里简化一点代码——希望我不会剥离任何必要的内容Java 单元测试gwt调度,java,google-app-engine,gwt,junit,guice,Java,Google App Engine,Gwt,Junit,Guice,我正试图用JUnit为gwt调度服务编写一些单元测试。使用调试器单步执行测试时出现以下错误: 自定义提供程序com.google.inject.OutOfScopeException中出错:无法访问作用域对象。我们当前没有在HTTP Servlet请求中,或者您可能忘记将com.google.inject.Servlet.GuiceFilter应用为该请求的Servlet筛选器 我将在这里简化一点代码——希望我不会剥离任何必要的内容 import junit.framework.TestCase
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();
}
}
}
服务请求实际上应该通过一个GuiceFilter,看起来没有设置该过滤器
关于注册过滤器还需要做哪些其他设置,您有什么想法吗?问题在于它说明了什么。您正在尝试访问作用域对象,但当前不在该作用域中。最可能的情况是,您的测试要求注入器提供一个
RequestScoped
对象,或者在注入依赖关系树中有一个RequestScoped
对象的对象,但是测试没有做任何事情来进入范围
在测试中绑定GuiceFilter
没有帮助,因为您的测试没有试图通过GuiceFilter
向servlet发送HttpServletRequest
最好的选择是对代码进行单元测试。孤立地创建类,注入mock
假设您想进行某种集成测试,您有三种选择:
bindScope(RequestScoped.class,new FakeScope)
的测试模块。FakeScope
类将实现Scope
,并具有进入和退出Scope的方法。您可能必须使用所依赖对象的伪实现来“播种”范围。看这个鬼。这是集成测试的最佳选择,IMHOServletScopes.scopeRequest
()在模拟请求范围内运行部分测试代码。这有点难看,因为您需要传递一个可调用的
HttpServletRequest
或HttpServletResponse
,那么事情可能会变得有点混乱。要正确设置这些类可能很困难。大多数类不应该直接或间接地依赖于servlet类。如果不是这样的话,您可能是做错了什么,或者您需要找到一个好的操作框架,使您的大多数代码不依赖于这些类
下面是方法1的一个示例,使用GUI中的SimpleScope
:
公共类LoggedInServiceTest扩展了TestCase{
私人最终提供者服务提供者;
私有最终SimpleScope FakerRequestScope=新SimpleScope();
私有最终HttpServletRequest=new FakeHttpServletRequest();
受保护的喷油器createInjector(){
返回Guice.createInjector(新的FakerRequestScopeModule(),
新的LoggedInServiceModule();
}
@凌驾
受保护的void setUp()引发异常{
super.setUp();
Injector=createInjector();
scope.enter();
serviceProvider=injector.getProvider(StandardDispatchService.class);
}
@凌驾
受保护的void tearDown()引发异常{
fakeRequestScope.exit()
super.tearDown();
}
public void testNotLoggedIn(){
fakeRequestScope.enter();
//填写请求的值
seed(FakeHttpServletRequest.class,request);
StandardDispatchService服务=serviceProvider.get();
GetProjectsAction=新建GetProjectsAction();
试一试{
执行(动作);
失败();
}捕获(预期为NotLoggeDineException){
}
}
私有类FakerRequestScopeModule扩展了AbstractModule(){
@凌驾
受保护的void configure(){
绑定(requestScope.class、fakeRequestScope);
绑定(HttpServletRequest.class)
.to(FakeHttpServletRequest.class)
.in(requestScope.class)
}
}
}
编写一个AppSession接口和两个实现:HttpAppSession和MockAppSession。
使服务器端处理程序依赖于AppSession,而不是直接依赖于HttpSession
- 使用Guice将HttpSession注入HttpAppSession。这是您将在生产中使用的,并且用于在真正的servlet容器中实际运行您的应用程序
- MockAppSession不应依赖于HttpSession、HttpServletRequest或任何其他GUI Http作用域。这是您将在测试期间使用的作用域
bind(AppSession.class).to(MockAppSession.class)
bind(MockAppSession.class).in(Singleton.class)
这会帮你解决问题。测试中的一些风格建议。1.安装程序应该受到保护,在做任何事情之前调用
super.setUp()
(TestCase.setUp()
不做任何事情,但如果更改基类,可能会出现问题)。2.不要在测试中捕获异常并调用fail()
,更改您的测试方法以声明它引发了异常
。如果测试引发了异常,它将自动失败。谢谢。测试实际上应该验证是否引发了正确的异常——但您是对的,我发布的简化代码并不完全漂亮。我最终测试的类依赖于HttpServletRequest/HttpSession通过@Inject Provider。有没有办法绕过它在调用注入的提供程序上的.get()时引发的NullPointerException?您必须将HttpServletRequest种子放入范围中。我添加了一个代码示例。这是针对哪个版本的GUI编写的?我注意到像bind()这样的方法在FakerRequestScope中,模块似乎被移动到bindScope(),等等。即使在这些更改之后,我仍然看到错误l
bind(AppSession.class).to(MockAppSession.class)
bind(MockAppSession.class).in(Singleton.class)