powermock mock 静态类,静态属性

本文介绍如何使用PowerMockito解决版本冲突问题,并演示了正确的静态类Mock顺序,确保静态方法和属性能够正确模拟。此外,还提供了配置依赖项的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.PowerMockito 版本问题

https://stackoverflow.com/questions/26192929/unable-to-run-junit-test-with-powermockrunner

<powermock.version>1.6.0</powermock.version>
update to
<powermock.version>1.6.1</powermock.version>

2.PowerMockito mock 静态类时初始化内存,以下顺序不能更改第二行先mock Objects.nonNull,再到第三行设置一把静态类
        PowerMockito.mockStatic(Objects.class);
        BDDMockito.given(Objects.nonNull("META-INF/version.properties")).willReturn(false);
        Whitebox.setInternalState(AppVersion.class, "VERSION_FILE_LOCATION", "None exist");
        AppVersion appVersion = new AppVersion() {
        };

测试类上面加注解
@RunWith(PowerMockRunner.class)
@PrepareForTest({AppVersion.class, Objects.class})

            <!-- mockito -->
            <dependency>
                <groupId>org.mockito</groupId>
                <artifactId>mockito-core</artifactId>
                <version>${mockito.version}</version>
            </dependency>


            <dependency>
                <groupId>org.powermock</groupId>
                <artifactId>powermock-module-junit4</artifactId>
                <version>${powermock.version}</version>
            </dependency>


            <dependency>
                <groupId>org.powermock</groupId>
                <artifactId>powermock-api-mockito</artifactId>
                <version>${powermock.version}</version>
                <exclusions>
                    <exclusion>
                        <groupId>org.mockito</groupId>
                        <artifactId>mockito-all</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>


            <dependency>
                <groupId>org.easymock</groupId>
                <artifactId>easymock</artifactId>
                <version>${easymock.version}</version>
            </dependency>
引用于:
mock 方法
https://stackoverflow.com/questions/21105403/mocking-static-methods-with-mockito
mock 静态属性
https://stackoverflow.com/questions/5385161/powermock-testing-set-static-field-of-class

<think>我们正在讨论如何使用PowerMock来模拟静态方法。根据引用内容,我们可以总结出以下步骤: 1. **添加依赖**:首先需要在项目中配置PowerMock的依赖(如引用[1]所示)。 2. **使用特定的测试运行器**:在测试类上使用`@RunWith(PowerMockRunner.class)`注解(如引用[3]所示)。 3. **准备需要被模拟的类**:使用`@PrepareForTest`注解指定包含静态方法的类(如引用[3]中`@PrepareForTest({ BusinessUtil.class })`)。 4. **模拟静态方法**:在测试方法中,使用`PowerMockito.mockStatic(Class)`来模拟指定的类(如引用[3]中`PowerMockito.mockStatic(BusinessUtil.class)`)。 5. **设置模拟行为**:使用`Mockito.when()`来定义当调用静态方法时的返回值(如引用[3]中`Mockito.when(BusinessUtil.getAllUser()).thenReturn(expected)`)。 6. **执行测试**:调用被测试的方法,该方法内部会调用我们模拟的静态方法。 7. **验证结果**:使用断言来验证结果,也可以使用`PowerMockito.verifyStatic()`来验证静态方法是否被调用(注意:如果需要验证静态方法的调用,需要在验证之前调用`PowerMockito.verifyStatic()`,然后紧接着调用一次静态方法,以表明我们验证的是上一次调用之后发生的调用)。 另外,引用[2]提到的问题可能是因为没有正确配置或者没有使用`@PrepareForTest`注解,导致模拟没有生效。 下面是一个完整的示例代码,展示如何模拟一个静态方法: ```java import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import static org.mockito.Mockito.when; @RunWith(PowerMockRunner.class) @PrepareForTest({StaticClass.class}) // 指定包含静态方法的类 public class MyTest { @Test public void testStaticMethod() { // 模拟静态类 PowerMockito.mockStatic(StaticClass.class); // 设置静态方法的行为 when(StaticClass.staticMethod()).thenReturn("mocked value"); // 调用被测试的方法,该方法内部会调用StaticClass.staticMethod() // ... 这里调用你的被测试代码 ... // 验证静态方法被调用(如果需要) PowerMockito.verifyStatic(StaticClass.class); // 开始验证 StaticClass.staticMethod(); // 验证这个方法被调用了一次,如果不调用这行,则验证的是之前调用的次数 } } ``` 注意:在验证静态方法调用时,`PowerMockito.verifyStatic()`需要紧跟着一次对静态方法的调用(作为参数传递),这样做的目的是告诉PowerMock你要验证的是哪个方法以及验证其调用情况。但是,如果你只是验证调用次数,那么你需要在`verifyStatic`之后再次调用静态方法,这看起来有点奇怪,但实际上它表示的是验证最后一次调用之后是否发生了调用。因此,更常见的做法是使用如下方式: ```java // 验证静态方法被调用了一次 PowerMockito.verifyStatic(StaticClass.class, times(1)); StaticClass.staticMethod(); ``` 但是,上面的`times(1)`实际上是`Mockito`中的`VerificationMode`,需要静态导入`org.mockito.Mockito.times`。然而,在PowerMock中,更常见的做法是使用无参的`verifyStatic`,然后紧接着调用一次静态方法,表示验证该方法被调用了一次。如果要验证多次,可以使用: ```java // 验证静态方法被调用了两次 PowerMockito.verifyStatic(StaticClass.class, times(2)); StaticClass.staticMethod(); // 这里会验证被调用了两次?实际上这种写法并不正确。 ``` 实际上,正确的验证多次调用的写法是: ```java // 验证静态方法被调用了两次 PowerMockito.verifyStatic(StaticClass.class, Mockito.times(2)); StaticClass.staticMethod(); // 注意:这样写实际上只验证了一次调用,因为这里又调用了一次,所以总体验证会出错。 ``` 正确的做法是:在调用被测试方法之后,我们通过`verifyStatic`来验证之前对静态方法的调用次数。但是,由于静态方法可能在测试过程中被多次调用,所以我们需要在调用`verifyStatic`之后紧接着指定要验证的方法调用,并且这个调用不会真正执行,只是用于验证。然而,这种方式只能验证最后一次调用之后发生的调用次数,所以通常我们使用: ```java // 验证静态方法被调用了n次(包括之前的所有调用) PowerMockito.verifyStatic(StaticClass.class, Mockito.times(2)); // 验证总共调用了2次 StaticClass.staticMethod(); // 这里会检查最后一次调用之后是否又调用了两次?实际上,这种方式已经被废弃。 ``` 实际上,从PowerMock 1.5开始,推荐使用以下方式: ```java // 验证静态方法被调用了一次 PowerMockito.verifyStatic(StaticClass.class); StaticClass.staticMethod(); // 验证该方法被调用了一次(从开始到现在) // 如果要验证两次,则调用两次verifyStatic,每次后面跟着一次静态方法调用?这显然不合理。 ``` 因此,更常见的做法是,我们只关心静态方法是否被调用,而不关心调用次数,或者只验证一次调用。如果确实需要验证多次,可以使用: ```java // 设置模拟 PowerMockito.mockStatic(StaticClass.class); when(StaticClass.staticMethod()).thenReturn("something"); // 调用被测试方法,该方法内部调用两次StaticClass.staticMethod() // 验证静态方法被调用了两次 PowerMockito.verifyStatic(StaticClass.class, times(2)); StaticClass.staticMethod(); ``` 但是,注意:上面的`times(2)`和紧接着的`StaticClass.staticMethod()`实际上只验证了该方法被调用了两次,因为`verifyStatic`会检查从开始到当前时刻,该方法被调用的次数。而紧接着的`StaticClass.staticMethod()`并不是真正的调用,而是告诉PowerMock我们要验证的是哪个方法以及验证其调用次数。然而,实际上,这种方式在PowerMock中已经被实现为:通过最后这行调用,它会检查之前记录的所有调用中,该静态方法被调用的总次数。所以,上面的代码会验证`staticMethod()`被调用了两次。 总结:使用`PowerMockito.verifyStatic(Class, VerificationMode)`后紧接着调用一次静态方法,可以验证该静态方法在之前的调用中,被调用的次数是否符合`VerificationMode`(如`times(2)`)。 重要提示:在测试结束时,如果需要验证静态方法被调用,通常需要调用`verifyStatic`,但如果不关心调用情况,可以省略验证步骤。 另外,注意:在同一个测试方法中,如果多次设置静态方法的行为,后面的设置会覆盖前面的设置。 最后,确保你的测试类使用了正确的注解,并且被模拟的类在`@PrepareForTest`中指定,否则模拟不会生效。 希望这个回答能帮助你。</think>### 如何使用 PowerMock 模拟静态方法 以下是使用 PowerMock 模拟静态方法的完整步骤(基于 Java 单元测试场景): #### 步骤 1:添加依赖 在 Maven 中配置 PowerMock 依赖: ```xml <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>2.0.9</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>2.0.9</version> <scope>test</scope> </dependency> ``` #### 步骤 2:编写测试代码 ```java import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; // 1. 使用 PowerMock 测试运行器 @RunWith(PowerMockRunner.class) // 2. 声明要模拟的类(包含静态方法) @PrepareForTest({StaticUtil.class}) public class ServiceTest { @Test public void testStaticMethod() { // 3. 模拟静态类 PowerMockito.mockStatic(StaticUtil.class); // 4. 设置模拟行为 PowerMockito.when(StaticUtil.getConfig("timeout")).thenReturn("1000"); // 5. 调用被测试方法(内部使用 StaticUtil.getConfig()) Service service = new Service(); String result = service.processConfig(); // 6. 验证结果 assertEquals("1000", result); // 7. 可选:验证静态方法调用 PowerMockito.verifyStatic(StaticUtil.class); StaticUtil.getConfig("timeout"); } } ``` #### 关键注解说明 1. `@RunWith(PowerMockRunner.class)` 启用 PowerMock 的测试执行器 2. `@PrepareForTest({ClassWithStaticMethod.class})` 声明需要字节码修改的类(必须包含静态方法的类) #### 常见问题解决 1. **模拟不生效** → 检查是否遗漏 `@PrepareForTest` 注解[^2] 2. **返回默认值** → 确保正确使用 `when().thenReturn()` 3. **验证调用失败** → 在 `verifyStatic()` 后立即调用目标静态方法 #### 技术原理 PowerMock 通过修改类的字节码和自定义类加载器来实现静态方法的模拟,这需要特殊的测试运行器和类级注解支持[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值