有了它(powermock)再也不担心单元测试不达标了
2020/5/3 17:25:45
本文主要是介绍有了它(powermock)再也不担心单元测试不达标了,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
为什么要写单元测试
- 优点:单元测试可以减少bug率,提升代码的质量。还可以通过单元测试来熟悉业务。
- 公司硬性要求:有些公司可能还会强制要求,每次新增代码、或者变更代码单测覆盖率要达到多少比例才能申请代码合并请求。
选择哪个单元测试框架
目前应用比较普遍的java单元测试工具 junit4+Mock(Mockito、jmock、EasyMock、powermock)。为什么会选择powermock? 在做单元测试的时候,我们会发现我们要测试的方法会有很多外部依赖的对象或者一些其他服务的调用比如说(发送邮件,网络通讯,soa调用)。 而我们没法控制这些外部依赖的对象。 为了解决这个问题,我们需要用到Mock来模拟这些外部依赖的对象,从而控制它们。只关心我们自己的业务逻辑是否正确。而这时powermock就起作用了,它不仅可以mock外部的依赖,还可以mock私有方法、final方法,总之它的功能很强大。
什么是powerMocker
PowerMock是一个框架,它以更强大的功能扩展了其他模拟库,例如EasyMock。 PowerMock使用自定义的类加载器和字节码操作来模拟静态方法,构造函数, 最终类和方法,私有方法,删除静态初始化程序等。通过使用自定义类加载器,无需对IDE或持续集成服务器进行任何更改,从而简化了采用过程。熟悉受支持的模拟框架的开发人员会发现PowerMock易于使用,因为整个期望API都是相同的, 无论是静态方法还是构造函数。PowerMock 旨在通过少量方法和注释扩展现有的API,以启用额外的功能。
常用注解
- @RunWith(PowerMockRunner.class) 告诉JUnit使用PowerMockRunner进行测试
- @PrepareForTest({DemoDao.class}) 所有需要测试的类列在此处,适用于模拟final类或有final, private, static, native方法的类
- @PowerMockIgnore({"javax.management.", "javax.net.ssl."}) 为了解决使用powermock后,提示classloader错误
- @SuppressStaticInitializationFor 不让静态代码加载 其他更多注解可以参考:github.com/powermock/p…
如何开始
JUnit 4.4及以上
<properties> <powermock.version>2.0.2</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样例
这是一个需要被mock的类里面有私有方法、静态方法、等等下面一一来演示各个方法的mock功能。
/** * * @Date: 2020/3/31 * @Description: */ @Repository public class DemoDao { public String mockPublicMethod(String type) throws Throwable { throw new Throwable(); } public final String mockFinalMethod(String type) throws Throwable { throw new Throwable(); } public static String mockStaticMethod(String type) throws Throwable { throw new Throwable(); } } /** * @Date: 2020/3/31 11:34 * @Description: */ @Component public class DemoService extends AbstractDemo{ @Autowired private DemoDao demoDao; public String mockPublicMethod() throws Throwable { return demoDao.mockPublicMethod("demo"); } public String mockFinalMethod() throws Throwable { return demoDao.mockFinalMethod("demo"); } public String mockStaticMethod() throws Throwable { return DemoDao.mockStaticMethod("demo"); } private String callPrivateMethod(String type) { return type; } public String mockPublicMethodCallPrivateMethod(String type) throws Throwable { return callPrivateMethodThrowable(type); } private String callPrivateMethodThrowable(String type) throws Throwable { throw new Throwable(); } public String mockExtendMethod(String type) throws Throwable { return getExtendMethod(); } public static String UUID = "uuid"; } 复制代码
mock普通公共方法
/** * @Date: 2020/4/24 14:22 * @Description: */ @RunWith(PowerMockRunner.class) public class DemoServiceTest { @InjectMocks private DemoService demoService; @Mock private DemoDao demoDao; /** * mock 普通方法 * @throws Throwable */ @Test public void mockPublicMethod() throws Throwable { String type = UUID.randomUUID().toString(); PowerMockito.when(demoDao.mockPublicMethod(any())).thenReturn(type); String result = demoService.mockPublicMethod(); Assert.assertEquals(type, result); } 复制代码
mock Final方法
跟普通方法是一样的,唯一的区别是需要在类上加入PrepareForTest注解
@RunWith(PowerMockRunner.class) @PrepareForTest(DemoDao.class) public class DemoServiceTest { @InjectMocks private DemoService demoService; @Mock private DemoDao demoDao; /** * mock final方法 * @throws Throwable */ @Test public void mockFinalMethod() throws Throwable { String type = UUID.randomUUID().toString(); PowerMockito.when(demoDao.mockFinalMethod(any())).thenReturn(type); String result = demoService.mockFinalMethod(); Assert.assertEquals(type, result); } 复制代码
mock静态方法(使用 PowerMockito.mockStatic)被mock的类也要用PrepareForTest注解修饰。
@RunWith(PowerMockRunner.class) @PrepareForTest(DemoDao.class) public class DemoServiceTest { @InjectMocks private DemoService demoService; @Mock private DemoDao demoDao; /** * mock 静态方法 * @throws Throwable */ @Test public void mockStaticMethod() throws Throwable { String type = UUID.randomUUID().toString(); PowerMockito.mockStatic(DemoDao.class); PowerMockito.when(DemoDao.mockStaticMethod(any())).thenReturn(type); String result = demoService.mockStaticMethod(); Assert.assertEquals(type, result); } 复制代码
调用 private方法
/** * 调用私有方法 * * @throws Throwable */ /** * 调用私有方法 * * @throws Throwable */ @Test public void callPrivateMethod() throws Throwable { // 第一种方式 String type = UUID.randomUUID().toString(); Method method = PowerMockito.method(DemoService.class, "callPrivateMethod", String.class); String result = (String) method.invoke(demoService, type); Assert.assertEquals(type, result); //第二种方式 String result1 = Whitebox.invokeMethod(demoService, "callPrivateMethod", type); Assert.assertEquals(type, result1); } 复制代码
mock 私有方法(被mock的类也要用PrepareForTest注解修饰。)
/** * mock私有方法 * * @throws Throwable */ @Test public void mockPrivateMethod() throws Throwable { String type = UUID.randomUUID().toString(); // 重点这一句 demoService = PowerMockito.spy(demoService); PowerMockito.doReturn(type).when(demoService,"callPrivateMethodThrowable",type); String result = demoService.mockPublicMethodCallPrivateMethod(type); Assert.assertEquals(type, result); } 复制代码
mock父类方法
/** * mock父类方法 * * @throws Throwable */ @Test public void mockExtendMethod() throws Throwable { String type = UUID.randomUUID().toString(); // 需要mock的父类的方法 Method method = PowerMockito.method(AbstractDemo.class, "getExtendMethod"); // InvocationHandler PowerMockito.replace(method).with((proxy, method1, args) -> type); String result = demoService.mockExtendMethod(type); Assert.assertEquals(type, result); } 复制代码
mock构造方法
public DemoService() { throw new NullPointerException(); } @Test public void mockConstructorMethod() throws Throwable { PowerMockito.whenNew(DemoService.class).withNoArguments().thenReturn(demoService); } 复制代码
mock字段
/** * mock 字段 */ @Test public void mockFiled(){ String uuid = UUID.randomUUID().toString(); Whitebox.setInternalState(DemoService.class, "UUID",uuid); Assert.assertEquals(DemoService.UUID, uuid); } 复制代码
结束
- 由于自己才疏学浅,难免会有纰漏,假如你发现了错误的地方,还望留言给我指出来,我会对其加以修正。
- 如果你觉得文章还不错,你的转发、分享、赞赏、点赞、留言就是对我最大的鼓励。
- 感谢您的阅读,十分欢迎并感谢您的关注。
这篇关于有了它(powermock)再也不担心单元测试不达标了的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-06-30uniAPP 实现全屏左右滚动滚动的效果-icode9专业技术文章分享
- 2024-06-30如何在本地使用授权或插件-icode9专业技术文章分享
- 2024-06-30伪静态规则配置方法汇总-icode9专业技术文章分享
- 2024-06-29易优CMS安装常见问题汇总-icode9专业技术文章分享
- 2024-06-28易优新手必读安装教程-icode9专业技术文章分享
- 2024-06-28忘记eyoucms后台密码怎么办?-icode9专业技术文章分享
- 2024-06-26终极指南:Scrum中如何设置需求优先级
- 2024-06-26AI大模型企业应用实战(25)-为Langchain Agent添加记忆功能
- 2024-06-26小白家庭 nas 搭建方案-icode9专业技术文章分享
- 2024-06-23AI大模型企业应用实战(14)-langchain的Embedding