Java 如何测试 Guice 注射?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2448013/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I test Guice injections?
提问by yeraycaballero
I gave to Google Guice the responsibility of wiring my objects. But, how can I test if the bindings are working well?
我让 Google Guice 负责连接我的对象。但是,我如何测试绑定是否运行良好?
For example, suppose we have a class A
which has a dependence B
. How can I test that B is injected correctly?
例如,假设我们有一个A
具有依赖关系的类B
。如何测试 B 是否正确注入?
class A {
private B b;
public A() {}
@Inject
public void setB(B b) {
this.b = b
}
}
Notice that A
hasn't got a getB()
method and I want to assert that A.b
isn't null
.
请注意,A
还没有getB()
方法,我想断言A.b
不是null
。
采纳答案by NamshubWriter
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.
对于任何复杂的 Guice 项目,您应该添加测试以确保模块可用于创建您的类。在您的示例中,如果 B 是 Guice 无法弄清楚如何创建的类型,那么 Guice 将无法创建 A。如果 A 不需要启动服务器但在您的服务器处理请求,这会导致问题。
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:
在我的项目中,我为非平凡的模块编写测试。对于每个模块,我使用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;
}
}
}
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.
注意测试如何只要求提供者。这足以确定 Guice 可以解析绑定。如果 LoginService 是由提供者方法创建的,则此测试不会测试提供者方法中的代码。
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."
此测试也不会测试您是否将正确的内容绑定到UserDao
,或者UserDao
范围是否正确。有些人会争辩说,这些类型的东西很少值得检查;如果有问题,它会发生一次。你应该“测试直到恐惧变成无聊为止”。
I find Module tests useful because I often add new injection points, and it's easy to forget to add a binding.
我发现模块测试很有用,因为我经常添加新的注入点,而且很容易忘记添加绑定。
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.
这些requireBinding()
调用可以帮助 Guice 在返回注入器之前捕获丢失的绑定!在上面的例子中,如果requireBinding()
调用不在那里,测试仍然可以工作,但我喜欢它们,因为它们可以作为文档。
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.
对于更复杂的模块(比如我的根模块),我可能会使用Modules.override()来覆盖我在测试时不需要的绑定(例如,如果我想验证我的根对象是否被创建,我可能不会不希望它创建一个将连接到数据库的对象)。对于简单的项目,您可能只测试顶级模块。
Note that Guice will not inject nullsunless 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不会注入空值,除非该字段被注解,@Nullable
因此您很少需要在测试中验证注入的对象是否为非空值。事实上,当我用 注释构造函数时,@Inject
我不会费心检查参数是否正确null
(事实上,我的测试经常注入null
构造函数以保持测试简单)。
回答by Alexander Malfait
I don't think you should test private members being set. Better to test against the public interface of your class. If member "b" wouldn't be injected, you'll probably get a NullPointerException executing your tests, which should be plenty of warning.
我认为您不应该测试正在设置的私有成员。最好针对类的公共接口进行测试。如果成员“b”不会被注入,您可能会在执行测试时遇到 NullPointerException,这应该是大量警告。
回答by gpampara
IMHO, you should not be testing that. The Google Guice guys have the unit tests to assert that the injections work as expected - after all, that's what Guice is designed to do. You should only be writing tests for your own code (A and B).
恕我直言,你不应该测试。Google Guice 的人有单元测试来断言注入按预期工作 - 毕竟,这就是 Guice 的设计目的。您应该只为自己的代码(A 和 B)编写测试。
回答by murungu
Another way to test your configuration is by having a test suite that tests your app end-to-end. Although end-to-end tests nominally test use cases they indirectly check that your app is configured correctly, (that all the dependencies are wired, etc etc). Unit tests on the other hand should focus exclusively on the domain, and not on the context in which your code is deployed.
另一种测试您的配置的方法是使用一个测试套件来端到端地测试您的应用程序。尽管端到端测试名义上测试用例,但它们间接检查您的应用程序是否配置正确,(所有依赖项都已连接等)。另一方面,单元测试应该只关注域,而不是部署代码的上下文。
I also agree with NamshubWriter's answer. I'm am not against tests that check configuration as long as they are grouped in a separate test suite to your unit tests.
我也同意 NamshubWriter 的回答。我不反对检查配置的测试,只要它们被分组在单独的测试套件中即可用于您的单元测试。