PowerMock与Mockito使用教程

本文介绍PowerMock框架在Mockito基础上的扩展功能,包括如何模拟静态方法、构造方法及私有方法等,通过示例展示了PowerMock的具体应用。

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

简介

Mockito无法实现对静态函数、构造函数、私有函数、Final 等函数的模拟,PowerMock是一个Java模拟框架,可用于解决通常被认为很难甚至无法测试的测试问题。 使用PowerMock,可以模拟静态方法,删除静态初始化程序,允许模拟而不依赖注入等等。 PowerMock通过在执行测试时在运行时修改字节代码来完成这些技巧。
本文主要是介绍PowerMock 在 Mockito 框架上扩展的功能。
PowerMock提供了一个名为“PowerMockito”的类,用于创建模拟/对象/类并验证,其他仍然可以使用Mockito来设置和验证(例如times(),anyInt())。

maven使用配置

对junit来说有版本不同的话,配置也不相同,我们这里只给出junit4.4以上版本,mockito2.x版本的maven配置,其他的可以参考github官方介绍:https://github.com/powermock/powermock/wiki/Getting-Started

<properties>
    <powermock.version>1.7.1</powermock.version>
</properties>
<dependencies>
   <dependency>
      <groupId>org.powermock</groupId>
      <artifactId>powermock-module-junit4</artifactId>
      <version>${powermock.version}</version>
      <scope>test</scope>
   </dependency>
   <dependency>
      <groupId>org.powermock</groupId>
      <artifactId>powermock-api-mockito2</artifactId>
      <version>${powermock.version}</version>
      <scope>test</scope>
   </dependency>
</dependencies>

所有用到PowerMock的类都需要@RunWith(PowerMockRunner.class)和@PrepareForTest注解。

1. mock静态方法

(1) 首先在测试类上添加@PrepareForTest注解

@PrepareForTest(Static.class) // Static.class 是包含静态方法的类。

(2) 调用PowerMockito.mockStatic()方法来模拟Static.class

PowerMockito.mockStatic(Static.class);

(3) 使用Mockito.when()来模拟期望的结果

Mockito.when(Static.firstStaticMethod(param)).thenReturn(value);

(4) 验证
第一步:调用PowerMockito.verifyStatic(Static.class)验证行为;
第二步:然后调用Static.class的静态方法进行验证

PowerMockito.verifyStatic(Static.class); // 1
Static.firstStaticMethod(param); // 2

下面给一个完整的示例:
定义一个包含静态方法的类Hello:

public class Hello {
    public static int getValue1(){
        return 1;
    }

    public static int getValue2(){
        return 2;
    }

}

下面是测试代码:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Hello.class)
public class PowerMockTest {

  @Test
  public void testGetValue() {
        PowerMockito.mockStatic(Hello.class);

         Mockito.when(Hello.getValue1()).thenReturn(444);
        Mockito.when(Hello.getValue2()).thenReturn(666);

        assertEquals(444, Hello.getValue1());
        assertEquals(666, Hello.getValue2());
    }
}

2. mock构造方法

比如有一个要测试的类Directory :

public class Directory {
    public boolean create(String path) {
        File file = new File(path);

        if (file.exists()) {
            throw new IllegalArgumentException("path already exists");
        }
        return file.mkdirs();
    }
}

为了测试create方法,我们可以对File进行mock,并对file的方法进行打桩,先看一下测试代码:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Directory.class)
public class DirectoryTest {

  @Test
  public void testCreate() throws Exception {
        String path = "mocked path";
        File mockFile = PowerMockito.mock(File.class);

        PowerMockito.whenNew(File.class).withArguments(path).thenReturn(mockFile);

        PowerMockito.when(mockFile.exists()).thenReturn(false);
        PowerMockito.when(mockFile.mkdirs()).thenReturn(true);

        assertTrue(new Directory().create(path));
    }
}

大致步骤如下
(1)通过PowerMockito.mock(File.class)来mock一个File对象;
(2)使用 whenNew().withArguments().thenReturn() 语句实现对具体类的构造函数的模拟操作;
(3)然后对于之前创建的模拟对象 mockFile使用 When().thenReturn() 语句,即可实现需要的所有功能,从而实现对被测对象的覆盖测试。

3. mock私有方法和静态方法

为了实现对类的私有方法或者是 Final 方法的模拟操作,需要 PowerMock 提供的另外一项技术:局部模拟。

在之前的介绍的模拟操作中,我们总是去模拟一整个类或者对象,然后使用 When().thenReturn()语句去指定其中值得关心的部分函数的返回值,从而达到搭建各种测试环境的目标。对于没有使用 When().thenReturn()方法指定的函数,系统会返回各种类型的默认值(具体值可参考官方文档)。

局部模拟则提供了另外一种方式,在使用局部模拟时,被创建出来的模拟对象依然是原系统对象,虽然可以使用方法 When().thenReturn()来指定某些具体方法的返回值,但是没有被用此函数修改过的函数依然按照系统原始类的方式来执行。

这种局部模拟的方式的强大之处在于,除开一般方法可以使用之外,Final 方法和私有方法一样可以使用。

参考如下所示的被测代码:

public final class PrivatePartialMockingExample {
    public String methodToTest() {
        return methodToMock("input");
    }

    private String methodToMock(String input) {
        return "REAL VALUE = " + input;
    }
}

为了保持单元测试的纯洁性,在测试方法 methodToTest()时,我们不希望受到私有函数 methodToMock()实现的干扰,为了达到这个目的,我们使用刚提到的局部模拟方法来实现 , 实现方式如下:

import  org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.junit.Assert.assertEquals;
import static org.powermock.api.mockito.PowerMockito.spy;
import static org.powermock.api.mockito.PowerMockito.verifyPrivate;
import static org.powermock.api.mockito.PowerMockito.when;

@RunWith(PowerMockRunner.class)
@PrepareForTest(PrivatePartialMockingExample.class)
public class PrivatePartialMockingExampleTest {
  @Test
  public void demoPrivateMethodMocking() throws Exception {
        final String expected = "TEST VALUE";
        final String nameOfMethodToMock = "methodToMock";
        final String input = "input";

        PrivatePartialMockingExample underTest = spy(new PrivatePartialMockingExample());

        /* Setup the expectation to the private method using the method name */ 
        when(underTest, nameOfMethodToMock, input).thenReturn(expected);

        assertEquals(expected, underTest.methodToTest());

        // Optionally verify that the private method was actually called
        verifyPrivate(underTest).invoke(nameOfMethodToMock, input);
    }
}

可以发现,为了实现局部模拟操作,用来创建模拟对象的函数从 mock() 变成了 spy(),操作对象也从类本身变成了一个具体的对象。同时,When() 函数也使用了不同的版本:在模拟私有方法或者是 Final 方法时,When() 函数需要依次指定模拟对象、被指定的函数名字以及针对该函数的输入参数列表。

后半部分摘自:https://www.ibm.com/developerworks/cn/java/j-lo-powermock/index.html

<think>好的,我现在需要帮助用户将Ubuntu 22.04.5 LTS升级到最新的LTS版本,也就是24.04。根据用户提供的引用内容,特别是引用[1]和引用[2],里面提到了升级的步骤和一些注意事项。首先,我需要确认用户当前的系统版本是22.04.5 LTS,然后按照正确的步骤进行升级。 首先,用户可能需要先更新现有的软件包,确保系统是最新的状态。引用[2]中提到在安装Java之前需要执行`sudo apt update`和`sudo apt upgrade`,这说明在升级系统前更新软件包是一个常规步骤。所以第一步应该是建议用户更新系统。 接下来,引用[1]指出升级到24.04需要安装`update-manager-core`包,并且修改发行版配置为`lts`。用户可能需要运行`do-release-upgrade`命令来启动升级过程。这里需要注意的是,用户可能已经安装了必要的工具,但需要确认配置是否正确。 另外,备份数据是非常重要的,引用[1]特别提到了备份个人数据,因此我应该提醒用户在升级前进行完整备份,避免数据丢失。同时,确保有稳定的网络连接和足够的电量或电源供应,尤其是在服务器环境中,断电可能导致升级失败。 在升级过程中,用户可能会遇到依赖问题或配置文件的更改,这时候需要根据提示处理,例如选择保留本地配置文件还是替换成新版本。引用[3]中提到了不同用户的Python包安装位置不同,这可能暗示在升级后某些软件的路径或配置需要重新检查,但升级系统本身可能不会直接影响用户安装的Python包,除非系统Python版本有变动。 最后,升级完成后需要重启系统,并验证版本号。用户可能需要检查是否有残余问题,比如服务是否正常运行,应用程序是否兼容新系统等。如果出现问题,可能需要参考官方文档或社区支持。 总结步骤应该是:备份→更新现有软件→安装升级工具→修改配置→执行升级→处理升级中的提示→重启→验证。同时,要提醒用户注意事项和可能遇到的问题,确保升级顺利进行。</think>### 分步指南:将 Ubuntu 22.04.5 LTS 升级到 24.04 LTS #### 1. **准备工作** - **备份重要数据**:使用工具如`rsync`、`tar`或云存储备份个人文件、配置文件及数据库[^1]。 - **确保网络稳定**:建议使用有线连接避免无线网络中断导致升级失败。 - **更新现有系统**: ```bash sudo apt update && sudo apt upgrade -y sudo apt dist-upgrade -y sudo apt autoremove --purge ``` 此步骤确保所有软件包为最新状态,减少依赖冲突[^2]。 #### 2. **安装升级工具** - 若未安装`update-manager-core`,执行: ```bash sudo apt install update-manager-core -y ``` - 修改发行版配置为LTS模式: ```bash sudo sed -i 's/Prompt=normal/Prompt=lts/' /etc/update-manager/release-upgrades ``` #### 3. **执行系统升级** - 启动升级进程: ```bash sudo do-release-upgrade -d ``` 参数`-d`强制检测开发中版本(适用于早期升级)。 - **交互式操作**: - 按提示确认软件包替换(默认选`Y`)。 - 配置文件冲突时,建议选择**保留本地版本**(按`N`),避免覆盖自定义配置[^3]。 #### 4. **完成升级** - 升级完成后重启系统: ```bash sudo systemctl reboot ``` - 验证版本: ```bash lsb_release -a ``` 输出应包含`Ubuntu 24.04 LTS`。 #### 5. **后续检查** - 检查服务状态:如Apache/Nginx、MySQL等是否正常运行。 - 重新安装第三方驱动:如NVIDIA显卡驱动或定制内核模块。 - 清理残余软件包: ```bash sudo apt autoremove --purge ``` #### 注意事项 1. **服务器环境**:建议在维护窗口操作,避免业务中断。 2. **Python环境兼容性**:若系统Python版本升级(如3.10→3.12),需检查虚拟环境路径是否需重建。 3. **回滚方案**:若升级失败,可通过备份镜像或快照恢复系统。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值