首页 文章

我如何测试Guice注射?

提问于
浏览
28

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

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

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

    @Inject
    public void setB(B b) {
        this.b = b
    }
}

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

4 回答

  • 4

    我认为你不应该测试私人成员的设置 . 最好测试你 class 的公共界面 . 如果不注入成员“b”,你可能会得到一个执行测试的NullPointerException,这应该是很多警告 .

  • 41

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

    在我的项目中,我为非平凡模块编写测试 . 对于每个模块,我使用requireBinding()来声明模块需要什么绑定但是没有使用JUnit4和JMock的示例:'t define. In my tests, I create a Guice injector using the module under test and another module that provides the required bindings. Here':

    /** 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;
        }
      }
    }
    

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

    此测试也不会测试您是否将正确的东西绑定到 UserDao ,或者 UserDao 的范围是正确的 . 有人会争辩说,那些类型的东西很少值得检查;如果有问题,它会发生一次 . 你应该"test until fear turns to boredom."

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

    requireBinding() 调用可以帮助Guice在返回注入器之前捕获缺失的绑定!在上面的例子中,如果没有 requireBinding() 调用,测试仍然可以工作,但我喜欢它们,因为它们用作文档 .

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

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

  • 2

    另一种测试配置的方法是使用测试套件来端到端测试您的应用程序 . 虽然端到端测试名义上测试用例,但它们会间接检查您的应用程序是否配置正确,(所有依赖项都是有线的等等) . 另一方面,单元测试应该只关注域,而不是关注部署代码的上下文 .

    我也同意NamshubWriter的回答 . 我不反对检查配置的测试,只要它们被分组到单元测试的单独测试套件中 .

  • -1

    恕我直言,你不应该测试 . 谷歌Guice家伙有单元测试断言注射按预期工作 - 毕竟,这就是Guice的目的 . 您应该只为自己的代码(A和B)编写测试 .

相关问题