我们平时写单元测试时经常会遇到调用抽象类或父类的方法,这些抽象方法可能是调用底层接口或数据库,需要mock掉,让抽象方法返回一个我们指定的值,以便测试当前代码逻辑的场景。

下面讲下Spock如何结合power mock实现动态mock抽象方法

一. 抽象方法或父类方法动态mock

AbstractService 是个抽象类,我们需要把它的方法 parentMethod 模拟掉,返回我们预先设置的"期望值"

代码示例:

public abstract class AbstractService {String parentMethod(){// 发起接口调用或数据库操作return "parentMethod value";
    }
}

SubService是继承AbstractService 的子类,在doSomething方法体里会调用抽象类的 parentMethod 方法逻辑,然后根据抽象方法 parentMethod 的返回值走不同的逻辑:

public class SubService extends AbstractService {
    @Autowired
    MoneyDAO moneyDAO;public String doSomething() {
        String parent = super.parentMethod(); // 调用抽象类或父类方法if ("parent1".equals(parent)) {// 执行parent1分支逻辑return "sub1";
        }if ("parent2".equals(parent)) {// 执行parent2分支逻辑return "sub2";
        }if ("parent3".equals(parent)) {// 执行parent3分支逻辑return "sub3";
        }return "other";
    }
}

如果要mock掉抽象类AbstractService 中的 parentMethod 方法, 并且每次mock的值不一样, 可以使用spock + powermock来实现:

单元测试代码如下:

/**
 * 测试抽象类方法或父类方法
 * @Author: www.javakk.com
 * @Description: 公众号:Java老K
 * @Date: Created in 14:53 2020/10/05
 * @Modified By:
 */@RunWith(PowerMockRunner.class)@PowerMockRunnerDelegate(Sputnik.class)@PrepareForTest([SubService.class])class AbstractServiceTest extends Specification {@Unroll
    def "测试抽象方法"() {
        given: "mock抽象类方法"
        def sub = PowerMockito.mock(SubService)
        PowerMockito.when(sub.parentMethod()).thenReturn(parentValue) // mock掉抽象类的parentMethod, 返回动态mock值:mockParentReturn
        PowerMockito.when(sub.doSomething()).thenCallRealMethod()
        expect: "调用doSomething方法"
        sub.doSomething() == result
        where: "验证分支场景"
        parentValue | result"parent1"   | "sub1""parent2"   | "sub2""parent3"   | "sub3""parent4"   | "other"
    }
}

使用power mock模拟掉抽象类的方法,返回一个变量parentValue,然后再放在Spock的where标签里,即可实现动态mock的效果,即每次调用返回的mock值都不一样:parent1parent2parent3 ...

二. 抽象方法+实例方法的动态mock

如果在SubService中还有引用其他实例对象的方法,比如下面的业务代码:

public class SubService extends AbstractService {
    @Autowired
    MoneyDAO moneyDAO; // 金额换算对象public String doSomethingAndDao() {
        String parent = super.parentMethod(); // 调用抽象类或父类方法
        BigDecimal money = moneyDAO.getExchangeByCountry(parent); // 获取对应国家的金额if ("parent1".equals(parent)) {return money + " CNY";
        }if ("parent2".equals(parent)) {return money + " USD";
        }if ("parent3".equals(parent)) {return money + " EUR";
        }return money.toString();
    }
}

如果即要mock掉抽象类AbstractService 中的 parentMethod 方法,又要mockmoneyDAO对象,可以使用 Whitebox.setInternalState 方式

单元测试代码如下:

/**
 * 测试抽象类方法或父类方法
 * @Author: www.javakk.com
 * @Description: 公众号:Java老K
 * @Date: Created in 14:53 2020/10/05
 * @Modified By:
 */@RunWith(PowerMockRunner.class)@PowerMockRunnerDelegate(Sputnik.class)@PrepareForTest([SubService.class])class AbstractServiceTest extends Specification {@Unroll
    def "测试抽象方法和实例方法"() {
        given: "mock抽象类方法"
        def sub = PowerMockito.mock(SubService)// mock掉抽象类的parentMethod, 返回动态mock值:mockParentReturn
        PowerMockito.when(sub.parentMethod()).thenReturn(parentValue)
        PowerMockito.when(sub.doSomethingAndDao()).thenCallRealMethod()
        def moneyDAO = Mock(MoneyDAO)//将Spockmock的对象moneyDAO使用powermock赋值给SubService的引用moneyDAO
        Whitebox.setInternalState(sub, "moneyDAO", moneyDAO)
        moneyDAO.getExchangeByCountry(_) >> money // 这样就可以使用spock的动态mock
        expect: "调用doSomething方法"
        sub.doSomethingAndDao() == result
        where: "验证分支场景"
        parentValue | money || result"parent1"   | 100   || "100 CNY""parent2"   | 200   || "200 USD""parent3"   | 300   || "300 EUR""parent4"   | 400   || "400"
    }
}

关于动态mock的更多用法可以参考这篇文章:Spock高级用法 - 动态mock

(完整的代码已上传到github,在公众号里回复spock即可获取github项目地址)

-END-推荐阅读:Spock高级用法 - 动态mockSpock代码讲解 - 静态方法测试Spock代码讲解 - void方法测试Spock代码讲解 - 异常测试Spock代码讲解 - if esle 分支场景测试


互联网一线java开发老兵,工作10年有余,梦想敲一辈子代码,以梦为码,不负韶华。

扫码关注Java老K,获取更多Java干货。

mockito mock void方法_Spock如何模拟抽象类方法相关推荐

  1. mockito mock void方法_一文让你快速上手 Mockito 单元测试框架(上)

    作者|mghio 编辑|包包 前言  在计算机编程中,单元测试是一种软件测试方法,通过该方法可以测试源代码的各个单元功能是否适合使用.为代码编写单元测试有很多好处,包括可以及早的发现代码错误,促进更改 ...

  2. mockito mock void方法_用过举手!SpringBoot 单元测试利器Mockito

    Mockito 是一种 Java mock 框架,他主要是用来做 mock 测试的,他可以模拟任何 Spring 管理的 bean.模拟方法的返回值.模拟抛出异常...等,在了解 Mockito 的具 ...

  3. mockito mock void方法_一文让你快速上手 Mockito 单元测试框架

    前言 在计算机编程中,单元测试是一种软件测试方法,通过该方法可以测试源代码的各个单元功能是否适合使用.为代码编写单元测试有很多好处,包括可以及早的发现代码错误,促进更改,简化集成,方便代码重构以及许多 ...

  4. mockito mock void方法_纯干货,浅谈Mockito在单元测试中的实际应用

    本文接上文"接口方没写代码,对接方只能停工吗?",在这里简单介绍Mockito在单元测试中的实际应用.本文使用场景较单一,如有雷同,不甚荣幸,闲言少叙,开门见山.本文将使用mock ...

  5. mockito mock void方法_使用 Junit + Mockito 实践单元测试!

    一.前言 相信做过开发的同学,都多多少少写过下面的代码,很长一段时间我一直以为这就是单元测试... @SpringBootTest @RunWith(SpringRunner.class) publi ...

  6. Mockito测试void方法会引发异常

    本文翻译自:Mockito test a void method throws an exception I have a method with a void return type. 我有一个vo ...

  7. java mock void_如何使用Mockito模拟void方法 - How to mock void methods with Mockito

    问题: How to mock methods with void return type? 如何用void返回类型模拟方法? I implemented an observer pattern bu ...

  8. 如何使用Mockito模拟void方法

    如何用void返回类型模拟方法? 我实现了一个观察者模式,但是我不能用Mockito模拟它,因为我不知道怎么做. 我试图在互联网上找到一个例子,但没有成功. 我的课看起来像这样: public cla ...

  9. java mock什么意思_java @Mock, @MockBean 与 Mockito.mock( ) 之间的差异

    纯Mockito库import org.mockito.Mock; ... @Mock MyService myservice; 和import org.mockito.Mockito; ... My ...

最新文章

  1. 基于PU-Learning的恶意URL检测
  2. 怎么查看oracle数据库数据量大小?
  3. Mono制作安装包让C#桌面应用程序脱离net framework步骤
  4. R语言处理1975-2011年的人口信息
  5. Objective-C ,ios,iphone开发基础:picker控件详解与使用,(实现省市的二级联动)
  6. Ocelot——初识基于.Net Core的API网关
  7. VS2013 MFC + OpenCV3.0 打开图片
  8. java程序编写需注意的问题
  9. 电子邮件如何追溯到他们的源IP地址
  10. Python 菜单中的分割线
  11. OCR表格识别——(二)
  12. 智能家居--domoticz配置和风天气 HTTP/HTTPS poller 的使用以及domoticz_updateDevice的介绍
  13. Encoded password does not look like BCrypt最新异常处理
  14. 【转载】SQL注入进阶
  15. Windows XP快捷键大全
  16. CF、MF、FM、FFM浅析
  17. pd 生成mysql 脚本_powerdesigner 生成数据库脚本
  18. 在没有Release的日子里
  19. 中国医科大学本科毕业论文答辩PPT模板
  20. 在Mac下使用MindMaster画思维导图(脑图)

热门文章

  1. mescroll上拉加载的实现
  2. python12个基本语法_12-25python基本语法
  3. python画一个祝福别人生日快乐_分享快乐给朋友的生日快乐祝福语生日贺卡句子...
  4. java经常会出现异常的是,“Java异常Exception”总结
  5. 用计算机求锐角A,B,计算机操作题
  6. android theme 使用方法,Android入门之Style与Theme用法实例解析
  7. android button自定义样式详解,Android自定义格式显示Button的布局思路
  8. Johnny and Another Rating Drop CodeForces - 1362C(规律)
  9. [蓝桥杯][算法提高VIP]A Careful Approach(全排列+二分)
  10. c语言switch中用ifelse,初学者求问:用if单分支选择语句替换switch语句?if.else呢...