假设我有一个匕首2模块如下,
@Module
interface Creator {
MyClass create();
}
我用它来创建MyClass的实例
class Instantiator {
void doSomething(){
MyClass clazz = DaggerCreator.create().create();
// do things with clazz
}
}
在我看来,我无法在Instantiator中有效地测试doSomething方法,因为我无法为MyClass提供模拟。
我错了吗?如果不是,我们应该谨慎地使用Dagger实例化吗?
答案 0 :(得分:1)
你说的是很难测试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
注入到您注入的顶级类中,但现在您可以确定您注入的对象是按预期运行的,因为它是可测试的。你使用Dagger的代码看起来有点不同寻常,但为了问题和答案之间的平等,我会使用你的习语。
class Instantiator {
private final DoerOfSomething doerOfSomething;
Instantiator() {
doerOfSomething = DaggerCreator.create().create();
}
void doSomething() {
doerOfSomething.doSomething();
}
}