如何测试 Guice 注射? [英] How do I test Guice injections?

查看:18
本文介绍了如何测试 Guice 注射?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我让 Google Guice 负责连接我的对象.但是,我如何测试绑定是否运行良好?

I gave to Google Guice the responsibility of wiring my objects. But, how can I test if the bindings are working well?

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

For example, suppose we have a class A which has a dependence B. How can I test that B is injected correctly?

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

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

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

Notice that A hasn't got a getB() method and I want to assert that A.b isn't null.

推荐答案

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

For any complex Guice project, you should add tests to make sure that the modules can be used to create your classes. In your example, if B were a type that Guice couldn't figure out how to create, then Guice won't be able to create A. If A wasn't needed to start the server but was needed when your server was handling a request, that would cause problems.

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

In my projects, I write tests for non-trivial modules. For each module, I use requireBinding() to declare what bindings the module requires but doesn't define. In my tests, I create a Guice injector using the module under test and another module that provides the required bindings. Here's an example using JUnit4 and 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 是由提供者方法创建的,则此测试不会测试提供者方法中的代码.

Notice how the test only asks for a provider. That's sufficient to determine that Guice could resolve the bindings. If LoginService was created by a provider method, this test wouldn't test the code in the provider method.

该测试也不会测试您是否将正确的内容绑定到 UserDao,或者 UserDao 的范围是否正确.有些人会争辩说,这些类型的东西很少值得检查;如果有问题,它会发生一次.你应该测试直到恐惧变成无聊."

This test also doesn't test that you binded the right thing to UserDao, or that UserDao was scoped correctly. Some would argue that those types of things are rarely worth checking; if there's a problem, it happens once. You should "test until fear turns to boredom."

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

I find Module tests useful because I often add new injection points, and it's easy to forget to add a binding.

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

The requireBinding() calls can help Guice catch missing bindings before it returns your injector! In the above example, the test would still work if the requireBinding() calls were not there, but I like having them because they serve as documentation.

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

For more complicated modules (like my root module) I might use Modules.override() to override bindings that I don't want at test time (for instance, if I want to verify that my root object to be created, I probably don't want it to create an object that will connect to the database). For simple projects, you might only test the top-level module.

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

Note that Guice will not inject nulls unless the field as annotated with @Nullable so you very rarely need to verify that the injected objects are non-null in your tests. In fact, when I annotate constructors with @Inject I do not bother to check if the parameters are null (in fact, my tests often inject null into the constructor to keep the tests simple).

这篇关于如何测试 Guice 注射?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆