PowerMock-单元测试

PowerMockito简介(以上都是自我琢磨,错误之处请批评指正)

在实际项目中写单元测试的过程中我们会发现需要测试的类有很多依赖,这些依赖项又会有依赖,导致在单元测试代码里几乎无法完成构建,尤其是当依赖项尚未构建完成时会导致单元测试无法进行。为了解决这类问题我们引入了Mock的概念,简单的说就是模拟那些尚未构建完成的类或者资源,用Mock模拟出来供测试使用。业内的Mock工具有很多,也已经很成熟了,这里我们将直接使用最流行的Mockito进行实战演练,完成mockito教程。

EasyMock 以及 Mockito 都因为可以极大地简化单元测试的书写过程而被许多人应用在自己的工作中,但是这两种 Mock工具都不可以实现对静态函数、构造函数、私有函数、Final 函数以及系统函数的模拟,但是这些方法往往是我们在大型系统中需要的功能。

以上简介参考源自:https://www.cnblogs.com/zishi/p/6780719.html

Demo用到的类

Controller类:

package demo.mock;

import java.io.File;

/**

* @author wangg

* @date  2018年3月14日 下午8:15:58

* @description

*/

public class Controller {

public boolean sentPost(){

System.out.println("发送post");

return true;

}

public final boolean isLive(){

System.out.println("isLive");

return false;

}

public static boolean isExist(File f) {

System.out.println("isExist");

return false;

}

}

Common类:

package demo.mock;

import java.io.File;

/**

* @author wangg

* @date  2018年3月14日 下午7:45:59

* @description

*/

public class Common {

private Controller controller;

public Controller getController() {

return controller;

}

public void setController(Controller controller) {

this.controller = controller;

}

/**

* 调用普通方法

* @param f

* @return

*/

public boolean callOrdinaryMethod(Controller controller){

System.out.println("Common....callOrdinaryMethod....start");

boolean result = controller.sentPost();

System.out.println("Common....callOrdinaryMethod.....over");

return result;

}

/**

* 调用静态方法

* @param f

* @return

*/

public boolean callStaticMethod(File f){

System.out.println("Common....callStaticMethod.....start");

boolean result = Controller.isExist(f);

System.out.println("Common....callStaticMethod.....end");

return result;

}

/**

* 调用final方法

* */

public boolean callFinalMethod(Controller controller){

System.out.println("Common....callFinalMethod.....start");

boolean result = controller.isLive();

System.out.println("Common....callFinalMethod.....end");

return result;

}

/**

* 调用内部方法

* */

public boolean callInsideMethod(Controller controller){

System.out.println("Common....callInsideMethod.....start");

boolean result = insideMethod();

System.out.println("Common....callInsideMethod.....end");

return result;

}

public boolean insideMethod(){

System.out.println("........insideMethod........");

return false;

}

/**

* 调用私有方法

* */

public boolean callPrivateMethod(){

System.out.println("Common......callPrivateMethod.... start..");

privateMethod();

System.out.println("Common......callPrivateMethod.... end..");

return false;

}

private void privateMethod() {

System.out.println("Common......privateMethod......");

}

}

CommonTest类:

package demo.mock.test;

import static org.junit.Assert.*;

import java.io.File;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.mockito.InjectMocks;

import org.mockito.Mock;

import org.powermock.api.mockito.PowerMockito;

import org.powermock.core.classloader.annotations.PrepareForTest;

import org.powermock.modules.junit4.PowerMockRunner;

import demo.mock.Common;

import demo.mock.Controller;

/**

* @author wangg

* @date  2018年3月14日 下午7:48:56

* @description

*/

@RunWith(PowerMockRunner.class)

public class CommonTest {

@InjectMocks

Common common = new Common();

@Mock //如果没有加该注解,common.getController() = null

Controller controller;

/**

* 测试

* @InjectMocks

* @Mock

* */

@Test

public void testAnnotation(){

System.out.println(common.getController());

System.out.println(common.getController() == null);

}

/**

* 普通方法测试

* */

@Test

@PrepareForTest(Controller.class)

public void testCallOrdinaryMethod(){

//虚拟一个controller对象

Controller controller = PowerMockito.mock(Controller.class);

//创建要测试的对象

Common common = new Common();

//拦截:当走到controller.sentPost()方法时,直接返回fasle,不执行sentPost()方法体

PowerMockito.when(controller.sentPost()).thenReturn(false);

//调用测试对象的方法

assertFalse(common.callOrdinaryMethod(controller));

}

/**

* final方法测试

* */

@Test

@PrepareForTest(Controller.class)

public void testCallFinalMethod(){

Controller controller = PowerMockito.mock(Controller.class);

Common common = new Common();

PowerMockito.when(controller.isLive()).thenReturn(true);

assertTrue(common.callFinalMethod(controller));

}

/**

* 静态方法错误示范

* @PrepareForTest(Util.class)没有添加

* */

// @Test

// public void testCallStaticMethodError() {

// File file = PowerMockito.mock(File.class);

// PowerMockito.mockStatic(Util.class);

// Common common = new Common();

// //错误代码

// PowerMockito.when(Util.isExist(file)).thenReturn(true);

// assertTrue(common.callStaticMethod(file));

// }

/**

* 静态方法测试

* */

@Test

@PrepareForTest(Controller.class)

public void testCallStaticMethod() {

File file = PowerMockito.mock(File.class);

PowerMockito.mockStatic(Controller.class);

Common common = new Common();

PowerMockito.when(Controller.isExist(file)).thenReturn(true);

assertTrue(common.callStaticMethod(file));

}

/**

* 使用spy进行部分模拟

* */

@Test

@PrepareForTest(Controller.class)

public void testCallInsideMethod(){

Common common = PowerMockito.spy(new Common());

Controller controller = PowerMockito.mock(Controller.class);

//调用内部方法

PowerMockito.doReturn(true).when(common).insideMethod();

// PowerMockito.doNothing().when(common).insideMethod();

assertTrue(common.callInsideMethod(controller));

}

/**

* 使用spy进行私有方法模拟

* @throws Exception

* */

@Test

@PrepareForTest(Common.class)//之前没有加该注解,一直报错,百思不得其解,后来忽然想到static,final,private 方法都的需要加这个注解才可以

public void testCallPrivateMethod() throws Exception {

Common common = PowerMockito.spy(new Common());

//调用私有方法

PowerMockito.doNothing().when(common,"privateMethod");

boolean result = common.callPrivateMethod();

assertFalse(result);

PowerMockito.verifyPrivate(common).invoke("privateMethod");

}

}

PowerMock两个重要的注解

@InjectMocks:创建一个实例对象,如果属性为Mock对象可以自动注入

@Mock:Mock一个对象,该对象可以自动注入到InjectMocks对象中(前提InjectMocks有属性为Mock类型)

@RunWith(PowerMockRunner.class)

@prepareForTest({MyObect.class})

PowerMock去mock静态,final或者私有方法时,需要加上这两个注解

如果调用时不加以上注解(测试类有错误示范)会报以下错误


通过看注解@PrepareForTest注解说明:

本人英语不好,直接拷贝到翻译上,大体的意思是:

这个注释告诉PowerMock为测试准备某些类。使用此注释定义的类通常是那些。需要对字节码进行操作。这包括最后的类和类。最终的、私有的、静态的或本地的方法应该被嘲笑。应该在实例化时返回模拟对象的类。

总结:

当我们做项目时,经常会依赖同事的接口(现在比较流行微服务嘛),有一种情况就是你这边开发完毕了,但是你依赖的接口还没有开发完毕,但是呢,你又还得做单元测试,要不然代码提交不了啊,母鸡啊!这怎么办呢,他完事不了,我测试不了啊!!!这时候Mock就派上用场了,通过Mock可以虚拟一个你依赖的服务,这样我们就可以愉快的做单元测试了~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,560评论 18 399
  • JAVA面试题 1、作用域public,private,protected,以及不写时的区别答:区别如下:作用域 ...
    JA尐白阅读 1,143评论 1 0
  • 硬盘是由一个个圆形的盘片组全起来的,从物理特性上看,硬盘盘片的转速越快,它的性能就越好,而且我们的磁道越靠外部,它...
    zejin阅读 661评论 0 1
  • 1. 人群中最美的她总是没人追 可气的是我身边的男人还总惦记着她 嘴上说的都是哥们儿义气 其实是怕没追到伤了面子 ...
    直到我们八十岁阅读 233评论 0 1