Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Mockito通过一系列依赖类注入mock_Java_Unit Testing_Dependency Injection_Mockito - Fatal编程技术网

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

Java 使用Mockito通过一系列依赖类注入mock,java,unit-testing,dependency-injection,mockito,Java,Unit Testing,Dependency Injection,Mockito,嗨,我已经实现了一系列类,它们使用dagger 2注入为每个类注入依赖项,我试图模拟这些类来运行我的单元测试,但它无法初始化从具有依赖项的较低层类中找到的依赖项 这在真实环境中运行良好,但不适用于测试 我尝试将所有依赖项标记为Spy或Mock,但它似乎只在调用的类的第一层上注入Mock。下面是标记为example1、Two、three的三个类,后面是测试类 ExampleOne有一个方法调用Example2中的另一个方法,然后最终调用ExampleThree中的另一个方法 public clas

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

这在真实环境中运行良好,但不适用于测试

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

ExampleOne有一个方法调用Example2中的另一个方法,然后最终调用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")
    }
}
只有示例二可以很好地注入模拟/间谍,而不是示例三

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
    }

}

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

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
的具体实现也可以单独进行测试。

这只是我的观点,但您应该通过构造函数或方法来实践显式依赖原则。接下来,应该隔离单元测试。在这种情况下,您不需要访问实现问题。您的类与实现问题紧密耦合,而不是抽象,这是一种代码味道。
ExampleOne
有一个依赖项,如果该依赖项不能被模仿/存根/伪造而没有副作用,那么目标类的设计就有问题。那么设计有缺陷吗?这是使用delegator模式,这是一种常见的设计模式。尽管如此,在其他情况下,您仍需要调用两个或三个需要创建依赖项的类。此解决方案在生产中工作得非常好,只是因为它在生产中工作并不使其成为最佳解决方案,或者设计没有缺陷。你只会招致技术债务。在指出一个依赖关系时,我指的是同一级别的依赖关系。在完整的生产代码中,对于每个类,我都有一个空构造函数,上面标记了注入,以自动连接它并在生产中工作。我是否应该删除@InjectExampleTower并将其添加到ExampleOne的构造函数中,就像对任何正在进行的类一样?@jonney注意到我的示例中的构造函数不是空的。还有,我的课程依赖于抽象,而不是具体化。@jonney我还建议你阅读坚实的原则。好的,谢谢,让我试一试。我认为这里的主要修复方法是使用ExampleTree作为构造函数的参数,我还将阅读坚实的原则OK it fixed my issue。谢谢我只是想知道这个方法。假设ExampleOne有多个依赖项。将所有这些依赖项添加到构造函数中而不是我们执行Inject-example2-Inject-exampletree-Inject-exampletree-Inject-exampletree而不是Inject/constructor(example2,Three,Four…)会看起来“丑陋”吗?