如何测试Guice注射剂?

发布于 2021-01-30 17:24:00

我让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

关注者
0
被浏览
103
1 个回答
  • 面试哥
    面试哥 2021-01-30
    为面试而生,有面试问题,就找面试哥。

    对于任何复杂的Guice项目,您都应该添加测试以确保可以使用这些模块来创建您的类。在您的示例中,如果B是Guice无法弄清楚如何创建的类型,则Guice将无法创建A。如果不需要A来启动服务器,但是当服务器处理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;
        }
      }
    }
    

    注意测试仅如何要求提供者。这足以确定Guice可以解析绑定。如果LoginService是由提供者方法创建的,则此测试不会测试提供者方法中的代码。

    此测试也不会测试您是否将正确的东西绑定到UserDao,或者绑定的UserDao范围正确。有些人会认为这类事情很少值得检查。如果有问题,它只会发生一次。您应该“测试,直到恐惧变成无聊为止”。

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

    这些requireBinding()调用可以帮助Guice在返回注射器之前捕获丢失的绑定!在上面的示例中,如果requireBinding()调用不存在,测试仍然可以进行,但是我喜欢使用它们,因为它们用作文档。

    对于更复杂的模块(例如我的根模块),我可能会使用Modules.override()覆盖测试时不需要的绑定(例如,如果我想验证要创建的根对象,我可能不会不想让它创建将连接到数据库的对象)。对于简单的项目,您可能只测试顶层模块。

    注意,除非用注释字段,Guice
    不会注入空值@Nullable因此您很少需要在测试中验证注入的对象是否为非空对象。实际上,当我用构造函数注释构造函数时,@Inject我不会费心检查参数是否正确null(实际上,我的测试通常会注入null到构造函数中以使测试保持简单)。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看