java - 如何验证 Guice 作用域在测试中的使用情况?

标签 java guice guice-3

我有一些测试,如果某些 Guice 作用域使用不当,我希望它们失败。例如,@Singleton不应该有任何 @RequestScoped@TestScoped依赖项( Provider<> 当然可以)。

在生产中,这已部分解决,因为在进入范围之前将构建急切绑定(bind)的单例,从而导致 OutOfScopeException秒。但是在开发中,单例会在范围内延迟创建,并且没有明显的问题。

根据 these 判断two Unresolved 问题,似乎没有简单的内置方法可以做到这一点。我可以使用 SPI 实现吗?我尝试使用 TypeListener但不清楚如何获取给定类型的依赖项。

最佳答案

这不是一个小问题,但绝对是个好问题!您提到的范围绑定(bind)问题可能有一个测试器。我想我可以让 Junit 运行器通过错误的绑定(bind)实践生成警告。我稍后会用它更新这篇文章。

现在有一个如何获取绑定(bind)范围的示例。

模块

public class ScopeTestModel extends ServletModule {

  @Override
  protected void configureServlets() {
    super
        .configureServlets();
    bind(Key.get(Object.class, Names.named("REQ1"))).to(Object.class).in(ServletScopes.REQUEST);
    bind(Key.get(Object.class, Names.named("REQ2"))).to(RequestScopedObject.class);

    bind(Key.get(Object.class, Names.named("SINGLETON1"))).to(Object.class).asEagerSingleton();
    bind(Key.get(Object.class, Names.named("SINGLETON2"))).to(Object.class).in(Scopes.SINGLETON);
    bind(Key.get(Object.class, Names.named("SINGLETON3"))).to(SingletonScopedObject.class);

    bind(Key.get(Object.class, Names.named("SESS1"))).to(Object.class).in(ServletScopes.SESSION);
    bind(Key.get(Object.class, Names.named("SESS2"))).to(SessionScopedObject.class);
  }
}

测试用例

public class TestScopeBinding {

  private Injector injector = Guice.createInjector(new ScopeTestModel());

  @Test
  public void testRequestScope() throws Exception {
    Binding<Object> req1 = injector.getBinding(Key.get(Object.class, Names.named("REQ1")));
    Binding<Object> req2 = injector.getBinding(Key.get(Object.class, Names.named("REQ2")));

    Scope scope1 = getScopeInstanceOrNull(req1);
    Scope scope2 = getScopeInstanceOrNull(req2);

    Assert.assertEquals(ServletScopes.REQUEST,scope1);
    Assert.assertEquals(ServletScopes.REQUEST,scope2);
  }

  @Test
  public void testSessionScope() throws Exception {
    injector.getAllBindings();
    Binding<Object> sess1 = injector.getBinding(Key.get(Object.class, Names.named("SESS1")));
    Binding<Object> sess2 = injector.getBinding(Key.get(Object.class, Names.named("SESS2")));

    Scope scope1 = getScopeInstanceOrNull(sess1);
    Scope scope2 = getScopeInstanceOrNull(sess2);

    Assert.assertEquals(ServletScopes.SESSION,scope1);
    Assert.assertEquals(ServletScopes.SESSION,scope2);
  }

  @Test
  public void testSingletonScope() throws Exception {
    injector.getAllBindings();
    Binding<Object> sng1 = injector.getBinding(Key.get(Object.class, Names.named("SINGLETON1")));
    Binding<Object> sng2 = injector.getBinding(Key.get(Object.class, Names.named("SINGLETON2")));
    Binding<Object> sng3 = injector.getBinding(Key.get(Object.class, Names.named("SINGLETON3")));

    Scope scope1 = getScopeInstanceOrNull(sng1);
    Scope scope2 = getScopeInstanceOrNull(sng2);
    Scope scope3 = getScopeInstanceOrNull(sng3);

    Assert.assertEquals(Scopes.SINGLETON,scope1);
    Assert.assertEquals(Scopes.SINGLETON,scope2);
    Assert.assertEquals(Scopes.SINGLETON,scope3);
  }

  private Scope getScopeInstanceOrNull(final Binding<?> binding) {
    return binding.acceptScopingVisitor(new DefaultBindingScopingVisitor<Scope>() {

      @Override
      public Scope visitScopeAnnotation(Class<? extends Annotation> scopeAnnotation) {
        throw new RuntimeException(String.format("I don't know how to handle the scopeAnnotation: %s",scopeAnnotation.getCanonicalName()));
      }

      @Override
      public Scope visitNoScoping() {
          if(binding instanceof LinkedKeyBinding) {
            Binding<?> childBinding = injector.getBinding(((LinkedKeyBinding)binding).getLinkedKey());
            return getScopeInstanceOrNull(childBinding);
          }
        return null;
      }

      @Override
      public Scope visitEagerSingleton() {
        return Scopes.SINGLETON;
      }

      public Scope visitScope(Scope scope) {
        return scope;
      }
    });
  }
}

作用域对象

@RequestScoped
public class RequestScopedObject extends Object {

}

@SessionScoped
public class SessionScopedObject extends Object {

}

@Singleton
public class SingletonScopedObject extends Object {

}

关于java - 如何验证 Guice 作用域在测试中的使用情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18474368/

相关文章:

guice-3 - Guice 3.0-启动时出现ArrayIndexOutOfBoundsException吗?

java - 使用 Guice 注入(inject)许多装饰实例——关于将 HessianServlet 与 Guice 混合

java - 在 AWS Lambda 中集成 Google Guice

java - Android 在神秘的 d() 方法中崩溃

java - 使用 Joda 时间求和持续时间

java - Google Guice 桌面应用程序 - 如何让它工作?

java - Juice 注入(inject)器抛出空指针异常

java - Guice - 创建到 java.lang.class 的绑定(bind)

java - 如何将时间戳转换为适当的日期格式?

java - 在java中为一副纸牌创建一个丢弃堆