使用 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()InstantiatordoSomething() 方法中被调用:

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();
    }

}