Unit testing 使用dagger 2创建对象的单元测试类

Unit testing 使用dagger 2创建对象的单元测试类,unit-testing,dagger-2,Unit Testing,Dagger 2,假设我有一个匕首2模块,如下所示 @Module interface Creator { MyClass create(); } 我用它来创建MyClass的一个实例 class Instantiator { void doSomething(){ MyClass clazz = DaggerCreator.create().create(); // do things with clazz } } 在我看来,我无法在实例化器中有效地

假设我有一个匕首2模块,如下所示

@Module
interface Creator {
    MyClass create();
}
我用它来创建MyClass的一个实例

class Instantiator {
    void doSomething(){
        MyClass clazz = DaggerCreator.create().create();
        // do things with clazz

    }
}
在我看来,我无法在实例化器中有效地测试doSomething方法,因为我无法为MyClass提供模拟


我错了吗?如果不是的话,我们应该少用Dagger实例化吗?

你说很难测试
组件的使用,这是正确的,因为这是一种静态方法。但比什么更难?下面是使用实例化的相同方法:

class Instantiator {
    void doSomething(){
        MyClass clazz = new MyClass();
        // do things with clazz

    }
}
还是很难测试,对吗

关键是使用尽可能少的
组件
(注入器),并在对象的构造函数中传递依赖项。Dagger 2使解析构造函数中的依赖项变得容易。这使得测试变得容易,因为您可以在构造函数中传入模拟对象

让我们重构您编写的可测试代码。假设
MyClass
包含一个方法,
fireLazers()
要测试的方法正在
实例化器
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();
    }

}

有道理。我担心的是,在一个类中实例化一个远离对象图根的对象会使单元测试变得困难,但正如您所说的,这个问题并不会消失。我想我能做的另一件事是注入ObjectCreator本身,我认为这是可能的,但我需要尝试一下。