我如何测试Guice注射?

yer*_*ero 30 java testing dependency-injection guice

我向Google Guice提供了连接我的对象的责任.但是,我如何测试绑定是否运行良好?

例如,假设我们有一个A具有依赖性的类B.如何测试B是否正确注入?

class A {
    private B b;
    public A() {}

    @Inject
    public void setB(B b) {
        this.b = b
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,A没有getB()方法,我想断言A.b不是null.

Nam*_*ter 45

对于任何复杂的Guice项目,您应该添加测试以确保可以使用这些模块来创建类.在你的例子中,如果B是Guice无法弄清楚如何创建的类型,那么Guice将无法创建A.如果不需要A来启动服务器但是在服务器处理时需要请求,这会导致问题.

在我的项目中,我为非平凡模块编写测试.对于每个模块,我使用requireBinding()来声明模块需要但不定义的绑定.在我的测试中,我使用被测模块创建了一个Guice注入器,另一个模块提供了所需的绑定.这是使用JUnit4和JMock的示例:

/** Module that provides LoginService */
public class LoginServiceModule extends AbstractModule {
  @Override 
  protected void configure() {
    requireBinding(UserDao.class);
  }

  @Provides
  LoginService provideLoginService(UserDao dao) {
    ...
  }
}

@RunWith(JMock.class)
public class LoginServiceModuleTest {
  private final Mockery context = new Mockery();

  @Test
  public void testModule() {
    Injector injector = Guice.createInjector(
        new LoginServiceModule(), new ModuleDeps());

    // next line will throw an exception if dependencies missing
    injector.getProvider(LoginService.class);
  }

  private class ModuleDeps extends AbstractModule {
    private final UserDao fakeUserDao;

    public ModuleDeps() {
      fakeUserDao = context.mock(UserDao.class);
    }

    @Override 
    protected void configure() {}

    @Provides
    Server provideUserDao() {
      return fakeUserDao;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意测试仅询问提供者.这足以确定Guice可以解决绑定问题.如果LoginService是由提供程序方法创建的,则此测试不会测试提供程序方法中的代码.

该测试也没有测试您绑定正确的事情UserDao,或者说UserDao是正确的作用域.有人会争辩说,那些类型的东西很少值得检查; 如果有问题,它会发生一次.你应该"测试,直到恐惧变成无聊."

我发现模块测试很有用,因为我经常添加新的注入点,并且很容易忘记添加绑定.

requireBinding()电话可以帮助吉斯赶上失踪绑定返回你的喷油器之前!在上面的例子中,如果requireBinding()调用不存在,测试仍然可以工作,但我喜欢它们,因为它们用作文档.

对于更复杂的模块(比如我的根模块),我可能会使用Modules.override()来覆盖我在测试时不想要的绑定(例如,如果我想验证我的根对象是否要创建,我可能不会不希望它创建一个将连接到数据库的对象.对于简单项目,您可能只测试顶级模块.

请注意,Guice 不会注入空值,除非该字段是注释的,@Nullable因此您很少需要验证注入的对象在测试中是否为空.事实上,当我注释构造函数时,@Inject我不打算检查参数是否null(实际上,我的测试经常注入null构造函数以保持测试简单).

  • “我的测试经常向构造函数中注入null以保持测试简单” =>可能表明您的类可能没有那么紧密 (2认同)