当前位置: 首页 > 工具软件 > PowerMock > 使用案例 >

powerMock单元测试

皇甫智明
2023-12-01

1 Mock的优缺点分析

1.1 Mock的好处

一、由于其他系统模块出错引起本模块的测试错误,我们可以采用mock隔离,避免干预;
二、开发过程中,只要交互双方定义好接口,团队之间可以并行工作,进程互不影响;
三、依赖系统无法响应,或者响应异常时,可以用mock Object代替,快速反应,不会影响测试进度;
四、提前接入测试,提供测试效率,当接口定义好后,测试人员就可以创建Mock,把接口添加到自动化测试环境,提前开始测试,起到测试驱动开发效果;
五、可以有效的增加覆盖,接口涉及入参,或者业务逻辑复杂的情况,某些场景无法通过正常手段进行操作,可以通过mock虚拟模拟;

1.2 使用Mock 可能存在的风险

一、测试过程中如果大量使用Mock,mock测试的场景失去了真是性,可能会导致在后续的系统性测试时才发现bug,使得缺陷发现的较晚,可能会造成后续修复成本更大;

1.3 为什么使用powerMock

一、PowerMock能够完美的mock静态、final、私有方法等,而其它mock工具是不能完美兼容的。

1.4 为什么要使用H2

一、单测的过程中涉及到大量的数据库操作时,使用H2可以最大限度的保证测试的真实性。

2. 相关依赖

mockito jar引入

 <properties>
        <mockito.version>2.26.0</mockito.version>
        <powermock.version>2.0.7</powermock.version>
    </properties>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>

powermock jar引入

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

Mock时修改私有变量的属性

<dependency>
<groupId>springframework</groupId>
<artifactId>spring-mock</artifactId>
<version>1.2.6</version>
</dependency>

jakarta的依赖

<dependency>
<groupId>jakarta.servlet.jsp</groupId>
<artifactId>jakarta.servlet.jsp-api</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
<scope>test</scope>
</dependency>

3.代码示例和说明

3.1 powerMock 配置

import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
public class BaseTest2 {

// 初始化
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
}

3.2 业务代码Mock

import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;

/声明需要mock的静态方法所在类
@PrepareForTest({PojoUtils.class, UUID.class})
//忽略类 有些代码不影响代码逻辑但是会导致mock报错,直接忽略掉就可以了
@PowerMockIgnore({"io.fabric8.kubernetes.*"})
public class OperatorServiceImplTest extends BaseTest2 {

//Mock 对象
@InjectMocks
private OperatorService operatorService = new OperatorServiceImpl();

//Mock 对象成员变量
@Mock
private EksConfig eksConfig;

@Mock
private JobClientService clientService;

@Mock
private MinglveDQCService qualityService;

@Mock
private EksService eksService;

@Mock
private EngineService engineService;

@Mock
private TaskService taskService;

@Mock
private TaskWorkspaceMapper taskWorkspaceMapper;

@Mock
private EksUtils eksUtils;

@Mock
private CosUtils cosUtils;



@Before
public void init(){
//修改私有成员变量的值
ReflectionTestUtils.setField(operatorService, "configUrlPrefix",
"wedata-agent-1257305158.cos.ap-beijing.myqcloud.com");

VisiableThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();
//核心线程数目
executor.setCorePoolSize(20);
//指定最大线程数a
executor.setMaxPoolSize(64);
//队列中最大的数目
executor.setQueueCapacity(10000);
//线程名称前缀
executor.setThreadNamePrefix("defaultThreadPool_");
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
//CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
//对拒绝task的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//线程空闲后的最大存活时间
executor.setKeepAliveSeconds(10);
//加载
executor.initialize();
//修改私有成员变量的值
ReflectionTestUtils.setField(operatorService, "executor",
executor);



//Mock 静态方法
PowerMockito.mockStatic(PojoUtils.class, UUID.class);

//Mock 静态方法的返回
KubeConf kubeConf = new KubeConf();
kubeConf.setCaCert("abc");
kubeConf.setClusterId("123");
kubeConf.setClusterName("abc");
kubeConf.setHost("122.0.0.1");
kubeConf.setPort(8080);
kubeConf.setRequestSchema("abc");
kubeConf.setToken("abc");
PowerMockito.when(PojoUtils.getFromEksInfo(Mockito.any())).thenReturn(kubeConf);

final String id = "493410b3-dd0b-4b78-97bf-289f50f6e74f";
UUID uuid = UUID.fromString(id);
PowerMockito.when(UUID.randomUUID()).thenReturn(uuid);



}

@Test
public void dispatcher() {
TaskWorkspaceInstance instance = new TaskWorkspaceInstance();

//Mock 实例方法
Mockito.when(taskWorkspaceMapper
.getOneWorkspaceByState(Mockito.anyInt(), Mockito.anyInt()))//与参数列表保持一致
.thenReturn(instance);//循环调用时支持返回一个集合
JobClientInstance jobClientInstance = new JobClientInstance();
jobClientInstance.setState(1);
List<JobClientInstance> clientInfos = Lists.newArrayList(jobClientInstance);

Mockito.when(clientService
.findAllScrap(Mockito.any(), Mockito.any())).thenReturn(clientInfos);

EKSInstance eksInfo = new EKSInstance();
Mockito.when(eksService
.FindByClusterId(Mockito.any(), Mockito.any())).thenReturn(eksInfo);
operatorService.dispatcher();
}



}

 powermock mock 局部变量

//FileOperations 在QualityTaskQueryServiceImpl类中被调用的
@PrepareForTest({QualityTaskQueryServiceImpl.class})
public class QualityTaskQueryServiceImplTest extends BaseTest1 {   
 @Test
    public void trialRun1() {
        TrialTaskReq trialTask = new TrialTaskReq();
        trialTask.setExprId(1);
        trialTask.setScheduleTime("2021-09-14 00:00:00");
        trialTask.setExpression("nopartition");

        PowerMockito.when(HttpUtils.executePostWithJson(Mockito.any(), Mockito.any()))
                .then((Answer<String>) invocation -> "{\"message\":\"123\",\"code\":\"SUCCESS\"}");
        //mock 局部变量
        FileOperations fileOperations = PowerMockito.mock(FileOperations.class);
        try {
            PowerMockito.whenNew(FileOperations.class).withAnyArguments().thenReturn(fileOperations);
            PowerMockito.doNothing().when(fileOperations).upload(Mockito.anyString(), Mockito.anyString(), Mockito.anyString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        qualityTaskQueryService.trialRun(trialTask);


    }
}

 类似资料: