4

如何模拟修改私有变量的私有方法?

class SomeClass{
    private int one;
    private int second;

    public SomeClass(){}

    public int calculateSomething(){
        complexInitialization();
        return this.one + this.second;
    }

    private void complexInitialization(){
        one = ...
        second = ...
    }
}
4

3 回答 3

8

你不这样做,因为你的测试将取决于它正在测试的类的实现细节,因此会很脆弱。您可以重构您的代码,以便您当前正在测试的类依赖于另一个对象来执行此计算。然后你可以模拟被测类的这种依赖关系。或者您将实现细节留给类本身并充分测试它的可观察行为。

您可能遇到的问题是您没有将命令和查询完全分离到您的类中。calculateSomething看起来更像是一个查询,但complexInitialization更像是一个命令。

于 2013-08-29T07:42:00.863 回答
2

假设其他答案指出此类测试用例很脆弱,并且测试用例不应基于实现,并且如果您仍想模拟它们,则应依赖于行为,那么这里有一些方法:

PrivateMethodDemo tested = createPartialMock(PrivateMethodDemo.class,
                                "sayIt", String.class);
String expected = "Hello altered World";
expectPrivate(tested, "sayIt", "name").andReturn(expected);
replay(tested);
String actual = tested.say("name");
verify(tested);
assertEquals("Expected and actual did not match", expected, actual);

这就是您使用 PowerMock 的方式。

PowerMock 的expectPrivate()就是这样做的。

来自 PowerMock的测试用例,用于测试私有方法模拟

更新: 使用 PowerMock进行部分模拟有一些免责声明和问题

class CustomerService {

    public void add(Customer customer) {
        if (someCondition) {
            subscribeToNewsletter(customer);
        }
    }

    void subscribeToNewsletter(Customer customer) {
        // ...subscribing stuff
    }
}

然后你创建一个 CustomerService 的 PARTIAL 模拟,给出你想模拟的方法列表。

CustomerService customerService = PowerMock.createPartialMock(CustomerService.class, "subscribeToNewsletter");
customerService.subscribeToNewsletter(anyObject(Customer.class));

replayAll();

customerService.add(createMock(Customer.class));

因此add(),在 CustomerService 模拟中是您想要测试的真实事物,并且对于subscribeToNewsletter()您现在可以像往常一样编写期望的方法。

于 2013-08-29T07:36:36.417 回答
1

电源模拟可能会在这里为您提供帮助。但通常我会让方法受到保护并覆盖以前的私有方法来做我想做的事情。

于 2013-08-29T07:36:24.027 回答