Java:对外部库的模拟调用以测试构造函数

Java:对外部库的模拟调用以测试构造函数,java,unit-testing,mockito,Java,Unit Testing,Mockito,我正在尝试对以下ClassA类的ClassAString构造函数进行单元测试: 我想模拟新的ExternalObject.parseStringstring调用,并用一个示例ExternalObject对象将其存根 我已经调查了Mockito,但似乎这项任务不可能与Mockito一起完成,因为: Mockito只能模拟方法,而不能模拟方法内的语句。 Mockito要求在模拟对象之前创建对象。所以,即使我将新的ExternalObject.parseString调用放在ClassA类中的一个单独的

我正在尝试对以下ClassA类的ClassAString构造函数进行单元测试:

我想模拟新的ExternalObject.parseStringstring调用,并用一个示例ExternalObject对象将其存根

我已经调查了Mockito,但似乎这项任务不可能与Mockito一起完成,因为:

Mockito只能模拟方法,而不能模拟方法内的语句。 Mockito要求在模拟对象之前创建对象。所以,即使我将新的ExternalObject.parseString调用放在ClassA类中的一个单独的方法中,如果没有ClassA实例,我也无法调用它。 在Mockito或任何其他mocking库中不重写大量代码就可以做到这一点吗?我愿意进行一些小的代码更改,以使其更易于测试。

为了模拟ExternalObject,您必须能够提供测试流中使用的ExternalObject实例

只要ExternalObject是在public ClassAString字符串中创建的,这就很困难了

为了使ClassA更易于测试,在构造ClassA时需要能够提供ExternalObject的实例

例如:

class ClassA{

    private ExternalObject externalObject;

    public ClassA() {
        super();
    }

    public ClassA(ExternalObject externalObject, String string) {
        super();
        this.externalObject = externalObject.parseString(string);
    }
}
然后可按如下方式进行测试:

public class ClasssATest {

    @Test
    public void someTest() {
        String input = "a string";
        ExternalObject externalObject = Mockito.mock(ExternalObject.class);
        Mockito.when(externalObject.parseString(eq(input))).thenReturn(externalObject);

        ClassA sut = new ClassA(externalObject, input);
        ...
    }
}
这里的关键点是:将外部依赖注入到类中。一旦您进行了此更改,测试就会变得更加容易,而且更一般地说,这种方法通过交换外部依赖项的输入/输出实现来更容易地更改系统行为。

为了模拟ExternalObject,您必须能够提供测试流中使用的ExternalObject实例

只要ExternalObject是在public ClassAString字符串中创建的,这就很困难了

为了使ClassA更易于测试,在构造ClassA时需要能够提供ExternalObject的实例

例如:

class ClassA{

    private ExternalObject externalObject;

    public ClassA() {
        super();
    }

    public ClassA(ExternalObject externalObject, String string) {
        super();
        this.externalObject = externalObject.parseString(string);
    }
}
然后可按如下方式进行测试:

public class ClasssATest {

    @Test
    public void someTest() {
        String input = "a string";
        ExternalObject externalObject = Mockito.mock(ExternalObject.class);
        Mockito.when(externalObject.parseString(eq(input))).thenReturn(externalObject);

        ClassA sut = new ClassA(externalObject, input);
        ...
    }
}

这里的关键点是:将外部依赖注入到类中。一旦您进行了此更改,测试将变得更加容易,而且更一般地说,这种方法通过交换外部依赖的输入/输出实现,使更改系统行为变得更加容易。

如果需要,请在投票前询问更多信息。不要嘲笑您不拥有的东西。将外部依赖封装在你控制的抽象后面,并将其注入依赖类。如果需要,请在投票前询问更多信息。不要嘲笑你不拥有的东西。将外部依赖项封装在您控制的抽象背后,并将其注入依赖类中。不应Mockito.whenexternalObject.parseString.thenReturnsome string;是Mockito.whenexternalObject.parseStringsome string.thenReturnexternalObject@glytching为什么使用Mockito.eq?这里似乎不需要。同意,字符串参数不需要。习惯的力量,我想。@glytching只是为了记录:Mockito.eq是不需要的,因为您与同一个对象进行比较,该对象在调用其equals方法时有资格返回true。如果cut传递同一个实例,或者cut内部创建的DTO具有equals实现,则这也适用于自定义对象;是Mockito.whenexternalObject.parseStringsome string.thenReturnexternalObject@glytching为什么使用Mockito.eq?这里似乎不需要。同意,字符串参数不需要。习惯的力量,我想。@glytching只是为了记录:Mockito.eq是不需要的,因为您与同一个对象进行比较,该对象在调用其equals方法时有资格返回true。如果cut传递同一个实例,或者cut内部创建的DTO具有equals实现,则这也适用于自定义对象。