Java:模拟调用外部库来测试构造函数

nar*_*ary 2 java unit-testing mockito

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

import ExternalObject;

class ClassA{

    private ExternalObject externalObject;

    public ClassA() {
        super();
    }

    public ClassA(String string) {
        super();
        this.externalObject = new ExternalObject().parseString(string);
    }
}
Run Code Online (Sandbox Code Playgroud)

我想模拟该new ExternalObject().parseString(string)调用并使用示例ExternalObject对象对其进行存根。

我研究过 Mockito,但似乎用 Mockito 不可能完成这项任务,因为:

  • Mockito 只能模拟方法,不能模拟方法内的语句。
  • Mockito 要求在模拟对象之前先创建对象。在开始模拟之前,Mockito 需要该类的一个实例。因此,即使我将new ExternalObject().parseString()调用放在 ClassA 类中的单独方法中,如果没有 ClassA 实例,我也无法调用它。

是否可以在 Mockito (或任何其他模拟库)中执行此操作而无需重写大量代码?我愿意对代码进行小的更改,以使其更易于测试。

gly*_*ing 5

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

只要在内部ExternalObject创建,这就会很困难。 public ClassA(String string)

为了使您的程序ClassA更具可测试性,您需要能够ExternalObject在构建时提供一个实例ClassA

例如:

class ClassA{

    private ExternalObject externalObject;

    public ClassA() {
        super();
    }

    public ClassA(ExternalObject externalObject, String string) {
        super();
        this.externalObject = externalObject.parseString(string);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后可以按如下方式进行测试:

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);
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

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