以下是我们在新应用中使用Guice的方式:
public class ObjectFactory {
private static final ObjectFactory instance = new ObjectFactory();
private final Injector injector;
private ObjectFactory() throws RuntimeException {
this.injector = Guice.createInjector(new Module1());
}
public static final ObjectFactory getInstance() {
return instance;
}
public TaskExecutor getTaskExecutor() {
return injector.getInstance(TaskExecutor.class);
}
}
Module1
定义了TaskExecutor
的构建方式。
在代码中,我们使用ObjectFactory.getInstance().getTaskExecutor()
来获取TaskExecutor
的实例。
在单元测试中,我们希望能够用FakeTaskExecutor
替换它,本质上我们希望在调用FakeTaskExecutor
时获得ObjectFactory.getInstance().getTaskExecutor()
的实例。
我正在考虑实施一个FakeModule
,它将由注射器而不是Module1
使用。
在Spring中,我们只使用@Autowired
注释,然后为Test
和Production
代码定义单独的bean,并使用Spring4JunitRunner
运行我们的测试;我们正在尝试与Guice做类似的事情。
答案 0 :(得分:4)
好的,首先要做的事情是:你似乎没有按照预期的方式使用Guice。一般来说,您希望使用Guice.createInjector()
来启动整个应用程序,并让它为您创建所有构造函数参数,而无需调用new
。
典型的用例可能是这样的:
public class Foo {
private final TaskExecutor executor;
@Inject
public Foo(TaskExecutor executor) {
this.executor = executor;
}
}
这是有效的,因为Foo的实例自己注入,一直到对象图。请参阅:Getting started
通过依赖注入,对象接受其构造函数中的依赖项。要构造对象,首先要构建其依赖项。但是要构建每个依赖项,您需要它的依赖项,依此类推。因此,当您构建对象时,您确实需要构建一个对象图。
手工构建对象图是劳动密集型,容易出错,并且使测试变得困难。相反,Guice可以为您构建对象图。但首先,Guice需要配置为完全按照您的意愿构建图形。
因此,通常情况下,您不会创建一个Singleton模式并将注入器放入其中,因为您应该很少在主类之外调用Guice.createInstance
;让喷射器为你完成所有的工作。
所有这些,为了解决你实际问的问题,你想使用Jukito。
JUnit,Guice和Mockito的综合力量。此外,它听起来像一个很酷的武术。
让我们回到上面描述的用例。在Jukito,您可以这样写FooTest
:
@RunWith(JukitoRunner.class)
public class FooTest {
public static class Module extends JukitoModule {
@Override
protected void configureTest() {
bindMock(TaskExecutor.class).in(TestSingleton.class);
}
}
@Test
public void testSomething(Foo foo, TaskExecutor executor) {
foo.doSomething();
verify(executor, times(2)).someMethod(eq("Hello World"));
}
}
这将验证由Mock object通过Jukito生成的Mockito是否已经使用字符串someMethod
两次调用方法"Hello World"
两次。< / p>
这就是为什么你不想以你描述的方式生成ObjectFactory
的对象; Jukito在单元测试中为你创建了Injector,并且很难注入Mock,你必须编写很多样板。