使用 testng、mockito 和 powermock 模拟系统 class 方法

Mocking System class method using testng, mockito and powermock

我目前正在为使用函数 System.getenv("some_environment_variable")

的遗留代码编写测试

当我尝试使用 mockito 和 powermock(在 testng 框架下使用)模拟这些变量时遇到问题

到目前为止我所做的是

@BeforeClass
public void setup() {
    PowerMockito.mockStatic(System.class);
    PowerMockito.when(System.getenv("hello")).thenReturn("world");
}

@Test
public void test() {
    assertEquals(System.getenv("hello"), "world");
}

但是当我尝试 运行 上面的代码时,出现以下错误:

org.mockito.exceptions.misusing.MissingMethodInvocationException: when() requires an argument which has to be 'a method call on a mock'. For example: when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:

  1. you stub either of: final/private/equals()/hashCode() methods. Those methods cannot be stubbed/verified. Mocking methods declared on non-public parent classes is not supported.

  2. inside when() you don't call method on mock but on some other object.

所以我读到并看到在尝试通过模拟 class 本身来模拟方法时引发了这个错误,但这里不是这种情况。

还有另一个 JUnit 库可以帮助您:system-rules,除其他外,它允许您设置和恢复环境变量。它与 JUnit @Rules

结合使用

在玩弄了一段时间之后,这是我设法做到的。

简而言之,为了让 powermockito 和 TestNG 相互协作,您必须执行以下操作(引用博客 post,其 link 在下面共享,以便答案是完整的,即使博客在以后的某个时间点不可用,也会很有用)

  1. 将 TestNG 配置为使用 PowerMock 对象工厂:您可以通过 <suite> 标记中的属性 object-factory 来执行此操作您的套件 xml 或通过 @org.testng.annotations.ObjectFactory 注释方法 returns powermock 对 TestNG 接口的实现 org.testng.IObjectFactoryorg.powermock.modules.testng.PowerMockObjectFactory (或)通过扩展 org.powermock.modules.testng.PowerMockTestCase

  2. 使用 @PrepareForTest 准备静态 class 以供 PowerMockito

  3. 模拟

详情请参考this博客。

这是一个工作示例:

import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.testng.IObjectFactory;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.ObjectFactory;
import org.testng.annotations.Test;

import static org.testng.Assert.assertEquals;

@PrepareForTest(System.class)
public class SampleTestClass {
    @BeforeClass
    public void setup() {
        PowerMockito.mockStatic(System.class);
        PowerMockito.when(System.getenv("hello")).thenReturn("world");
    }

    @Test
    public void test() {
        assertEquals(System.getenv("hello"), "world");
    }

    @ObjectFactory
    public IObjectFactory getObjectFactory() {
        return new org.powermock.modules.testng.PowerMockObjectFactory();
    }

}

我使用以下依赖项来创建此示例

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-testng</artifactId>
    <version>1.7.0</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito</artifactId>
    <version>1.7.0</version>
    <scope>test</scope>
</dependency>