Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 单元测试gwt调度_Java_Google App Engine_Gwt_Junit_Guice - Fatal编程技术网

Java 单元测试gwt调度

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

我正试图用JUnit为gwt调度服务编写一些单元测试。使用调试器单步执行测试时出现以下错误:

自定义提供程序com.google.inject.OutOfScopeException中出错:无法访问作用域对象。我们当前没有在HTTP Servlet请求中,或者您可能忘记将com.google.inject.Servlet.GuiceFilter应用为该请求的Servlet筛选器

我将在这里简化一点代码——希望我不会剥离任何必要的内容

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的方法。您可能必须使用所依赖对象的伪实现来“播种”范围。看这个鬼。这是集成测试的最佳选择,IMHO
  • 使用
    ServletScopes.scopeRequest
    ()在模拟请求范围内运行部分测试代码。这有点难看,因为您需要传递一个
    可调用的
  • 进行完整的端到端测试。启动服务器并使用Selenium发送请求。通过这种方式很难获得良好的覆盖率,所以我将把这留给您真正需要浏览器测试的东西
  • 如果您正在测试的类间接依赖于
    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作用域。这是您将在测试期间使用的作用域

    现在,您的Guice模块应注入AppSession实现,如下所示:

    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)