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

import ExternalObject;

class ClassA{

    private ExternalObject externalObject;

    public ClassA() {
        super();
    }

    public ClassA(String string) {
        super();
        this.externalObject = new ExternalObject().parseString(string);
    }
}


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

我已经研究了Mockito,但是看来Mockito无法完成此任务,因为:


Mockito只能模拟方法,而不能模拟方法中的语句。
Mockito要求在模拟对象之前先创建对象。 Mockito needs an instance of the class before you can begin mocking。因此,即使我将new ExternalObject().parseString()调用放在ClassA类的单独方法中,也不能在没有ClassA实例的情况下调用它。


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

最佳答案

为了模拟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);
    }
}


然后可以如下进行测试:

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);
        ...
    }
}


这里的关键点是:将外部依赖项注入您的类中。进行更改后,测试将变得更加容易,并且更广泛地讲,通过交换该外部依赖项的实现,此方法可以更轻松地更改系统行为。

07-28 03:34