Mocking of Private Methods Using PowerMock – 使用PowerMock对私有方法进行模拟

最后修改: 2017年 11月 7日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

One of the challenges of unit testing is mocking private methods.

单元测试的挑战之一是模拟私有方法。

In this tutorial, we’ll learn about how we can achieve this by using the PowerMock library – which is supported by JUnit and TestNG.

在本教程中,我们将了解如何通过使用PowerMock库来实现这一目标 – JUnit和TestNG支持该库。

PowerMock integrates with mocking frameworks like EasyMock and Mockito and is meant to add additional functionality to these – such as mocking private methods, final classes, and final methods, etc.

PowerMock集成了EasyMock和Mockito等嘲讽框架,旨在为这些框架增加额外的功能–比如嘲讽私有方法、最终类和最终方法等,

It does that by relying on bytecode manipulation and an entirely separate classloader.

它通过依赖字节码操作和一个完全独立的类加载器来做到这一点。

2. Maven Dependencies

2.Maven的依赖性

First, let’s add required dependencies to use PowerMock with Mockito and JUnit into our pom.xml:

首先,让我们在pom.xml中添加使用PowerMock与Mockito和JUnit的必要依赖。

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.7.3</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>1.7.3</version>
    <scope>test</scope>
</dependency>

The latest versions can be checked here and here.

最新的版本可以在这里这里检查。

3. Example

3.实例

Let’s get started with an example of a LuckyNumberGenerator. This class has a single public method for generating a lucky number:

让我们从一个LuckyNumberGenerator的例子开始。这个类有一个生成幸运数字的公共方法。

public int getLuckyNumber(String name) {
    saveIntoDatabase(name);
    if (name == null) {
        return getDefaultLuckyNumber();
    }
    return getComputedLuckyNumber(name.length());
}

4. Variations in Mocking of Private Methods

4.嘲弄私有方法的变化

For exhaustive unit testing of the method, we’d need to mock private methods.

为了对该方法进行详尽的单元测试,我们需要对私有方法进行模拟。

4.1. Method With No Arguments but With Return Value

4.1.没有参数但有返回值的方法

As a simple example, let’s mock the behavior of a private method with no arguments and force it to return the desired value:

作为一个简单的例子,让我们模拟一个没有参数的私有方法的行为,并强制它返回所需的值。

LuckyNumberGenerator mock = spy(new LuckyNumberGenerator());

when(mock, "getDefaultLuckyNumber").thenReturn(300);

In this case, we mock the private method getDefaultLuckyNumber and make it return a value of 300.

在这种情况下,我们模拟私有方法getDefaultLuckyNumber并使其返回一个300的值。

4.2. Method With Argument and Return Value

4.2.带有参数和返回值的方法

Next, let’s mock the behavior of a private method with an argument and force it to return the desired value:

接下来,让我们用一个参数来模拟一个私有方法的行为,并强制它返回所需的值。

LuckyNumberGenerator mock = spy(new LuckyNumberGenerator());

doReturn(1).when(mock, "getComputedLuckyNumber", ArgumentMatchers.anyInt());

In this case, we mock the private method and make it return 1.

在这种情况下,我们模拟这个私有方法并使其返回1。

Notice that we don’t care about the input argument and use ArgumentMatchers.anyInt() as a wildcard.

注意,我们并不关心输入参数,而是使用ArgumentMatchers.anyInt()作为通配符。

4.3. Verification of Invocation of a Method

4.3.对方法的调用的验证

Our final strategy is to use PowerMock to verify the invocation of a private method:

我们最后的策略是使用PowerMock来验证一个私有方法的调用。

LuckyNumberGenerator mock = spy(new LuckyNumberGenerator());
int result = mock.getLuckyNumber("Tyranosorous");

verifyPrivate(mock).invoke("saveIntoDatabase", ArgumentMatchers.anyString());

5. A Word of Caution

5.慎重声明

Finally, although private methods can be tested using PowerMock, we must be extra cautious while using this technique.

最后,尽管私有方法可以使用PowerMock进行测试,但我们在使用这一技术时必须格外谨慎。

Given the intent of our testing is to validate the behavior of a class, we should refrain from changing the internal behavior of the class during unit testing.

鉴于我们测试的目的是验证一个类的行为,我们应该避免在单元测试期间改变类的内部行为。

Mocking techniques should be applied to the external dependencies of the class and not to the class itself.

嘲弄技术应该应用于类的外部依赖关系,而不是类本身。

If mocking of private methods is essential for testing our classes, it usually indicates a bad design.

如果对私有方法的嘲弄对于测试我们的类是必不可少的,这通常表明了一个糟糕的设计。

6. Conclusion

6.结论

In this quick article, we showed how PowerMock could be used to extend the capability of Mockito for mocking and verification of private methods in the class under test.

在这篇快速的文章中,我们展示了如何使用PowerMock来扩展Mockito的能力,对被测类中的私有方法进行嘲讽和验证。

The source code of this tutorial can be found over on GitHub.

本教程的源代码可以在GitHub上找到over