Spring Boot 2 实践记录之 使用 Powermock、Mockito 对 UUID 进行 mock 单元测试

由于注册时,需要对输入的密码进行加密,使用到了 UUID、sha1、md 等算法。在单元测试时,使用到了 Powermock,记录如下。

先看下加密算法:

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;

import java.util.UUID;

public class Encrypt {
    /**
     * 密码加密
     * @param password 待加密的密码
     * @param md5 是否先用 md5 加密
     * @return 加密后的密码
     */
    public static String passwordGenerator(String password) {
        password = DigestUtils.md5Hex(password);
        String salt = DigestUtils.sha1Hex(UUID.randomUUID().toString()).substring(0, 4);
        String saltString = DigestUtils.sha1Hex(password + salt) + salt;
        String encryPassword = Base64.encodeBase64String(saltString.getBytes());
        return encryPassword;
    }
}

其中,UUID.randomUUID()、DigestUtils.md5Hex()、DigestUtils.sha1Hex()、Base64.encodeBase64String() 均为静态方法,而 uuid.toString() 则为 UUID 实例对象的方法。

对于 UUID 的 mock,需要两步:

第一步,是使用 mockito mock 一个 UUID 对象,并 mock 其在代码中使用的方法,这里要 mock 的是 toString() 方法。

第二步,是使用 powormockito,mock UUID 的 randomUUID() 方法,使其返回上一步 mock 的 uuid 对象,这样我们就能得到预期的 uuid 的方法(这里是 toString)的执行结果。

DigestUtils 和 Base64 的静态方法直接使用 powermockito 来 mock 就可以了。

 

具体步骤如下:

一、添加依赖包(使用 maven):

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

二、在测试类上添加 @Runwith 和 @PrepareForTest 注解

三、在测试方法中对类和对象进行 mock。

示例代码:

import org.apache.commons.codec.digest.DigestUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import org.apache.commons.codec.binary.Base64;
import java.util.UUID;

import static org.junit.Assert.*;

@RunWith(PowerMockRunner.class)
@PrepareForTest({UUID.class, DigestUtils.class, Encrypt.class, Base64.class})
public class EncryptTest {

    @Test
    public void passwordGeneratorWithMd5() {
        String randomString = "mbaefaeq";
        String salt = "abcd";
        String password = "123456";
        String rePassword = "654321";
        String twiceSaltMd5 = "hellomd5";

        // mock uuid 对象,使其 toString() 方法返回预定义的 randomString 字符串
        UUID uuid = PowerMockito.mock(UUID.class);
        Mockito.when(uuid.toString()).thenReturn(randomString);

        // mock UUID 类,使其 randomUUID() 方法返回刚刚 mock 的 uuid 对象
        PowerMockito.mockStatic(UUID.class);
        PowerMockito.when(UUID.randomUUID()).thenReturn(uuid);

        // mock DigestUtils 类,使其 sha1Hex() 方法在接收预定义的 randomString 参数时,返回预定义的 salt 字符串
        PowerMockito.mockStatic(DigestUtils.class);
        PowerMockito.when(DigestUtils.sha1Hex(randomString)).thenReturn(salt);

        // 使 mock 的 DigestUtils 类的 md5Hex 方法,在接受预定义的 password 时,生成预定义的 rePassword 字符串
        PowerMockito.when(DigestUtils.md5Hex(password)).thenReturn(rePassword);

        // 使 mock 的 DigestUtils 类的 sha1Hex() 方法在接收预定义的 rePassword 和 salt 时,返回 预定义的 twiceSaltMd5 字符串
        PowerMockito.when(DigestUtils.sha1Hex(rePassword + salt)).thenReturn(twiceSaltMd5);

        // mock Base64 类,使其encodeBase64String() 方法在接收 预定义的串时,返回预定义的加密后密码
        PowerMockito.mockStatic(Base64.class);
        String imencryptpassword = "imencryptpasswordwithmd5";
        PowerMockito.when(Base64.encodeBase64String((twiceSaltMd5 + salt).getBytes())).thenReturn(imencryptpassword);

        // 调用加密方法,并验证结果
        String encryptPassword = Encrypt.passwordGenerator("123456");
        assertEquals(imencryptpassword, encryptPassword);
    }
}

 

posted on 2019-02-24 11:23  刘兴伟  阅读(2687)  评论(0编辑  收藏  举报

导航