如何用假测试模块替换Guice模块进行单元测试?

时间:2015-08-04 16:43:18

标签: java spring unit-testing guice

以下是我们在新应用中使用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注释,然后为TestProduction代码定义单独的bean,并使用Spring4JunitRunner运行我们的测试;我们正在尝试与Guice做类似的事情。

1 个答案:

答案 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,你必须编写很多样板。