使用 dagger 2 创建对象的单元测试 类
Unit testing classes that use dagger 2 to create objects
假设我有一个 dagger 2 模块如下,
@Module
interface Creator {
MyClass create();
}
我正在使用它创建 MyClass 的实例
class Instantiator {
void doSomething(){
MyClass clazz = DaggerCreator.create().create();
// do things with clazz
}
}
在我看来,我无法有效地测试 Instantiator 中的 doSomething 方法,因为我无法为 MyClass 提供模拟。
我错了吗?如果不是,我们是否应该谨慎使用 Dagger 实例化?
你说很难测试 Component
注入器的使用是正确的,因为这是一个静态方法。但比什么更难?这是使用实例化的相同方法:
class Instantiator {
void doSomething(){
MyClass clazz = new MyClass();
// do things with clazz
}
}
仍然很难测试,对吗?
重点是尽可能少地使用 Component
(注入器),并在对象的构造函数中传递依赖项。 Dagger 2 使得解析构造函数中的依赖关系变得容易。这使得测试变得容易,因为您可以在构造函数中传入模拟对象。
让我们将您编写的代码重构为可测试的。假设 MyClass
包含一个方法,您要测试的 fireLazers()
在 Instantiator
的 doSomething()
方法中被调用:
public class DoerOfSomething {
private final MyClass myClass;
@Inject
public DoerOfSomething(MyClass myClazz) {
this.myClass = myClazz;
}
public void doSomething() {
myClass.fireLazers();
}
}
现在您可以使用模拟对象编写这样的测试:
public void DoerOfSomethingTest {
//mocks
MyClass mockMyClass;
//system under test
DoerOfSomething doerOfSomething;
@Before
public void setUp() {
mockMyClass = Mockito.mock(MyClass.class);
}
@Test
public void whenDoSomething_thenInteractsWithMyClass() {
//arrange
doerOfSomething = new DoerOfSomething(mockMyClass);
//act
doerOfSomething.doSomething();
//assert
verify(mockMyClass).fireLazers();
}
}
当然,您现在需要将 DoerOfSomething
注入您正在注入的顶层 class,但现在您可以确定您正在注入的对象正在按预期运行,因为它是可测试的。您使用 Dagger 的代码看起来有点不寻常,但为了问题和答案之间的平等,我会使用您的习语。
class Instantiator {
private final DoerOfSomething doerOfSomething;
Instantiator() {
doerOfSomething = DaggerCreator.create().create();
}
void doSomething() {
doerOfSomething.doSomething();
}
}
假设我有一个 dagger 2 模块如下,
@Module
interface Creator {
MyClass create();
}
我正在使用它创建 MyClass 的实例
class Instantiator {
void doSomething(){
MyClass clazz = DaggerCreator.create().create();
// do things with clazz
}
}
在我看来,我无法有效地测试 Instantiator 中的 doSomething 方法,因为我无法为 MyClass 提供模拟。
我错了吗?如果不是,我们是否应该谨慎使用 Dagger 实例化?
你说很难测试 Component
注入器的使用是正确的,因为这是一个静态方法。但比什么更难?这是使用实例化的相同方法:
class Instantiator {
void doSomething(){
MyClass clazz = new MyClass();
// do things with clazz
}
}
仍然很难测试,对吗?
重点是尽可能少地使用 Component
(注入器),并在对象的构造函数中传递依赖项。 Dagger 2 使得解析构造函数中的依赖关系变得容易。这使得测试变得容易,因为您可以在构造函数中传入模拟对象。
让我们将您编写的代码重构为可测试的。假设 MyClass
包含一个方法,您要测试的 fireLazers()
在 Instantiator
的 doSomething()
方法中被调用:
public class DoerOfSomething {
private final MyClass myClass;
@Inject
public DoerOfSomething(MyClass myClazz) {
this.myClass = myClazz;
}
public void doSomething() {
myClass.fireLazers();
}
}
现在您可以使用模拟对象编写这样的测试:
public void DoerOfSomethingTest {
//mocks
MyClass mockMyClass;
//system under test
DoerOfSomething doerOfSomething;
@Before
public void setUp() {
mockMyClass = Mockito.mock(MyClass.class);
}
@Test
public void whenDoSomething_thenInteractsWithMyClass() {
//arrange
doerOfSomething = new DoerOfSomething(mockMyClass);
//act
doerOfSomething.doSomething();
//assert
verify(mockMyClass).fireLazers();
}
}
当然,您现在需要将 DoerOfSomething
注入您正在注入的顶层 class,但现在您可以确定您正在注入的对象正在按预期运行,因为它是可测试的。您使用 Dagger 的代码看起来有点不寻常,但为了问题和答案之间的平等,我会使用您的习语。
class Instantiator {
private final DoerOfSomething doerOfSomething;
Instantiator() {
doerOfSomething = DaggerCreator.create().create();
}
void doSomething() {
doerOfSomething.doSomething();
}
}