Java 我如何用假测试模块代替Guice模块进行单元测试?
以下是我们在新应用程序中的使用方式:Java 我如何用假测试模块代替Guice模块进行单元测试?,java,spring,unit-testing,guice,Java,Spring,Unit Testing,Guice,以下是我们在新应用程序中的使用方式: public class ObjectFactory { private static final ObjectFactory instance = new ObjectFactory(); private final Injector injector; private ObjectFactory() throws RuntimeException { this.injector = Guice.createInjector(new
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
,本质上,我们希望在调用ObjectFactory.getInstance().getTaskExecutor()
时获得FakeTaskExecutor
的实例
我正在考虑实现一个假模块
,该模块将由喷油器使用,而不是模块1
在春季,我们只需使用
@Autowired
注释,然后为Test
和Production
定义单独的bean,并使用Spring4JunitRunner
运行我们的测试;我们正在尝试对Guice进行类似的操作。好的,首先要做的事情是:您似乎没有按照预期的方式使用Guice。一般来说,您希望使用Guice.createInjector()
启动整个应用程序,并让它为您创建所有构造函数参数,而无需调用new
典型的用例可能是这样的:
public class Foo {
private final TaskExecutor executor;
@Inject
public Foo(TaskExecutor executor) {
this.executor = executor;
}
}
@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"));
}
}
这是因为Foo的实例本身被注入到对象图中。见:
通过依赖项注入,对象在其构造函数中接受依赖项。要构造对象,首先要构建其依赖项。但是要构建每个依赖项,您需要它的依赖项,等等。因此,当您构建一个对象时,您确实需要构建一个对象图
手工构建对象图是劳动密集型的,容易出错,并且使测试变得困难。相反,Guice可以为您构建对象图。但首先,需要配置Guice以完全按照您的需要构建图形
因此,通常情况下,您不会创建单例模式并将注入器放入其中,因为您不应该在主类之外调用Guice.createInstance
;让喷油器为您完成所有工作
话虽如此,要解决您实际询问的问题,您需要使用 JUnit、Guice和Mockito的综合能力。而且这听起来像是一种很酷的武术 让我们回到我上面描述的用例。在朱基托,你可以这样写
FooTest
:
public class Foo {
private final TaskExecutor executor;
@Inject
public Foo(TaskExecutor executor) {
this.executor = executor;
}
}
@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"));
}
}
这将验证由via Jukito生成的您的,已经使用字符串“Hello World”
调用了方法someMethod
两次
这就是为什么您不希望以您描述的方式使用
ObjectFactory
生成对象;Jukito在其单元测试中为您创建了注入器,因此很难使用模拟注入器,您必须编写大量的样板文件。好的,首先要做的是:您似乎没有按照预期的方式使用Guice。一般来说,您希望使用Guice.createInjector()
启动整个应用程序,并让它为您创建所有构造函数参数,而无需调用new
典型的用例可能是这样的:
public class Foo {
private final TaskExecutor executor;
@Inject
public Foo(TaskExecutor executor) {
this.executor = executor;
}
}
@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"));
}
}
这是因为Foo的实例本身被注入到对象图中。见:
通过依赖项注入,对象在其构造函数中接受依赖项。要构造对象,首先要构建其依赖项。但是要构建每个依赖项,您需要它的依赖项,等等。因此,当您构建一个对象时,您确实需要构建一个对象图
手工构建对象图是劳动密集型的,容易出错,并且使测试变得困难。相反,Guice可以为您构建对象图。但首先,需要配置Guice以完全按照您的需要构建图形
因此,通常情况下,您不会创建单例模式并将注入器放入其中,因为您不应该在主类之外调用Guice.createInstance
;让喷油器为您完成所有工作
话虽如此,要解决您实际询问的问题,您需要使用 JUnit、Guice和Mockito的综合能力。而且这听起来像是一种很酷的武术 让我们回到我上面描述的用例。在朱基托,你可以这样写
FooTest
:
public class Foo {
private final TaskExecutor executor;
@Inject
public Foo(TaskExecutor executor) {
this.executor = executor;
}
}
@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"));
}
}
这将验证由via Jukito生成的您的,已经使用字符串“Hello World”
调用了方法someMethod
两次
这就是为什么您不希望以您描述的方式使用
ObjectFactory
生成对象;Jukito在其单元测试中为您创建了注入器,而注入模拟将非常困难,您必须编写大量的样板文件。您研究过模拟吗?Mockito是我推荐的API。FakeTaskExecutor
可以是模拟的,也可以是双重测试,我不知道如何在ObjectFactory
中拦截注入器。Mockito和PowerMock是实现这一点的唯一方法吗?如果是的话,我们是否错误地使用了Guice。您是否研究过mocking?Mockito是我推荐的API。FakeTaskExecutor
可以是模拟的,也可以是双重测试,我不知道如何在ObjectFactory
中拦截注入器。Mockito和PowerMock是否是实现这一点的唯一方法,如果是,我们是否错误地使用了Guice。谢谢,这很有帮助。我们将首先回顾如何使用guice。谢谢,这很有帮助。我们将首先回顾如何使用guice。