使用Mockito通过一系列依赖类注入Mocks

时间:2018-01-16 16:20:43

标签: java unit-testing dependency-injection mockito

您好我已经实现了一系列使用dagger 2 Injection为每个类注入依赖项的类,我试图模拟它们来运行我的单元测试但是它无法初始化从较低层类中找到的依赖项有依赖。

这在真实的环境中工作正常,但不适用于测试

我尝试将所有依赖项标记为Spy或Mock,但它似乎只是在我调用的类的第一层上注入模拟。下面是三个标记为ExampleOne,Two,Three的类,其次是测试类。

ExampleOne有一个方法可以调用ExampleTwo中的另一个方法,然后最后从ExampleThree调用另一个方法。

只有ExampleTwo才能使mock / spy注入正常而不是ExampleThree。

public class ExampleOne{

    @Inject
    ExampleTwo exampleTwo;

    //implementations below

    public void doSomethingOne(){
        exampleTwo.doSomethingTwo;
    }
}


public class ExampleTwo{

    @Inject
    ExampleThree exampleThree

    public void doSomethingTwo(){
        exampleThree.doPrintHello();
    }
}

public class ExampleThree{

    public void doPrintHello(){
        Log.d("Print","Hello")
    }
}

以下是我的测试

@RunWith(MockitoJUnitRunner.class)
public class TestExamples(){

    @InjectMocks
    ExampleOne exampleOne

    @Spy
    ExampleTwo exampleTwo = new ExampleTwo();

    @Spy
    ExampleThree exampleThree = new ExampleThree();

    @Test
    void test(){

        exampleOne.doSomethingOne();

        //some testing code here
    }

}

1 个答案:

答案 0 :(得分:1)

通过构造函数注入或方法注入实践显式依赖性原则。接下来,应该分离单元测试。在这种情况下,您不需要访问实现问题。您的类与实现问题紧密相关,而不是代码气味的抽象。

public class ExampleOne {    
    ExampleTwo exampleTwo;

    @Inject    
    public ExampleOne(ExampleTwo exampleTwo) {
        this.exampleTwo = exampleTwo;
    }

    //implementations below

    public void doSomethingOne(){
        exampleTwo.doSomethingTwo();
    }
}

public interface ExampleTwo {
    void doSomethingTwo();
}

public class ConcreteExampleTwo implements ExampleTwo {
    private ExampleThree exampleThree;

    @Inject    
    public ConcreteExampleTwo(ExampleThree exampleThree) {
        this.exampleThree = exampleThree;
    }

    public void doSomethingTwo(){
        exampleThree.doPrintHello();
    }
}

public interface ExampleThree {
    void doPrintHello();
}

//...code removed for brevity

ExampleOne在该级别有一个依赖项,如果这些依赖项无法模拟/存根/伪造而没有副作用,那么目标类的设计就会出现问题。

@RunWith(MockitoJUnitRunner.class)
public class TestExamples(){

    @Mock
    ExampleTwo exampleTwo;

    @InjectMocks
    ExampleOne exampleOne

    @Test
    void test(){

        exampleOne.doSomethingOne();

        verify(exampleTwo).doSomethingTwo();
    }    
}

通过上述建议的更改ExampleOne可以单独测试,而不会产生任何影响。

ExampleTwo的具体实现也可以单独测试。