Mockito框架下如何优雅的验证调用Mock对象方法的入参

这篇具有很好参考价值的文章主要介绍了Mockito框架下如何优雅的验证调用Mock对象方法的入参。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

该文章已同步至个人微信公众号[不能止步],欢迎关注。

1. 场景

在单元测试场景中,一种典型的场景是为了测试某一个类(Component Under Test, 简称CUT)而需要mock其依赖的的类。示例如下:

// 被测组件
public Class Order {
    private final OrderRepository orderRepository;
    
    public void create(CreateOrderDTO createOrder)
        validateCreateOrDer(createOrder);

        var order = processOrder(createOrder);

         orderRepository.save(order);
}

为了验证CUT业务实现的正确性,通常需要验证传给调用Mock对象的方法的参数的正确性。如果采用Mockito测试框架,一般可以按如下方式实现测试用例:

public Class OrderServiceTest {
    private final OrderRepository orderRepository = mock(OrderRepository.class);
    private final OrderService orderService = new OrderService(orderRepsitory);
    
    public void shouldSuccessWhenCreateOrder() {
         when(orderRepository.save(any).thenReturn(any());
         CreateOrderDTO createOrder = ...
         
         orderService.create(createOrder);
    
          // 验证参数是否与期望的一致
          verify(orderRepository, times(1)).save(argThat(order -> 
                order.userId().equals(createOrder.userId()) &&
                order.price() == 100));
    }
}    

2. 问题

采用上述方法(argThat)测试Mock对象的方法的入参的方式虽然可以验证入参是否符合期望,但细看代码,我们依然会发现几个问题。

  • 测试代码不美观,如果待验证的参数比较多,要用很多个&&连接;
  • 测试用例失败时无法给出是哪一个参数不正确,如上例中,在argThat中的lambda function表达式返回false时,测试用例失败的信息无法让开发者直接知道是userId还是price不符合期望,开发者还需要进行代码调试以确认到底是哪个参数不符合期望。
Argument(s) are different! Wanted:
orderRepository.save(
    <custom argument matcher>
);

Actual invocations have different arguments:
orderRepository.save(
   captor.demo.persistence.entity.Order@441aa7ae
);

3. 如何优雅的验证Mock对象的方法的入参

在Mockito测试框架下,Mockit提供了对Mock对象方法的入参捕获,其做法是:

  • 用MockitoExtension.class作为测试的执行引擎;
  • 使用@Captor注解定义一个参数捕获对象,并在CUT调用的被Mock对象的方法中传入定义的参数捕获对象;
  • 从定义的参数捕获对象中获得捕获的参数,使用assert进行验证。

采用该方法对上述示例的改进如下:

// 1. 使用MockitoExtension测试执行引擎
@ExtendWith(MockitoExtension.class)
public Class OrderServiceTest {
    private final OrderRepository orderRepository = mock(OrderRepository.class);
    private final OrderService orderService = new OrderService(orderRepsitory);
    
    //2. 使用@Captor注解定义一个参数捕获对象,泛型类型为待捕获的参数类型
    @Captor
    private ArgumentCaptor<Order> orderCaptor;
    
    public void shouldSuccessWhenCreateOrder() {
         when(orderRepository.save(any).thenReturn(any());
         CreateOrderDTO createOrder = ...
         
         orderService.create(createOrder);
    
          //3. 被Mock对象的方法中传入定义的参数捕获对象,注意需要调用参数捕获对象的capture方法
          verify(orderRepository, times(1)).save(orderCaptor.capture());
          //4. 从定义的参数捕获对象获得捕获的入参,使用assert进行验证
          var order = orderCaptor.getValue();
          assertThat(order.userId()).isEqualTo(createOrder.userId());
          assertThat(order.price()).isEuqalTo(100);
    }
} 

对比一下argThat和@Captor两种测试Mock对象的方法参数的方法,使用@Captor这种方法具有:文章来源地址https://www.toymoban.com/news/detail-484770.html

  • 代码美观,修改容易;
  • 测试用例失败时能够快速定位出哪个参数不符合期望。
org.opentest4j.AssertionFailedError: 
Expected :100
Actual   :50

到了这里,关于Mockito框架下如何优雅的验证调用Mock对象方法的入参的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 掌握C#中异步魔法:同步方法如何优雅调用异步方法

      概述: 上述C#示例演示了如何在同步方法中调用异步方法。通过使用`async`和`await`,实现了同步方法对异步方法的调用。建议使用`await`而不是`Result`来避免潜在的死锁问题。这种模式在处理异步任务时能够提高代码的可读性和性能。 在C#中,从同步方法调用异步方法

    2024年03月25日
    浏览(39)
  • 针对mockito框架在单元测试中出现Mybatis-Plus链式调用的解决方案

    1、 调用其他service层方法 2、 调用本service层方法 3、其他问题

    2024年01月24日
    浏览(42)
  • Mock&Mockito使用手册

    mock  测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。这个虚拟的对象就是mock对象。mock对象就是真实对象在调试期间的代替品; Mock 对象 :模拟对象的概念就是我们想要创建一个可以替代实际对象的对象,

    2024年02月11日
    浏览(35)
  • 单元测试(mock) 错误org.mockito.Mockito.framework()Lorg/mockito/MockitoFramework;解析

      如果您觉得有用的话,记得给 博主点个赞,评论,收藏一键三连啊 ,写作不易啊^ _ ^。   而且听说 点赞的人每天的运气都不会太差 ,实在白嫖的话,那欢迎常来啊!!! 01 准备 01::01 安装maven dependency helper插件和maven helper插件 用来分析你的依赖 打开idea 选择 File - Settin

    2023年04月08日
    浏览(36)
  • 单元测试之- mock工具mockito

     常用的mock工具mockito 在编写单元测试时,需要mock依赖的对象,减少依赖对象对测试的影响,Mocktio是常用的mock工具之一,那么mockito提供了哪些功能呢? Mock对象的创建和配置:Mockito可以通过简单的语法创建mock对象,并允许你配置mock对象的行为。 Mock对象的验证:Mockito提供

    2024年02月13日
    浏览(39)
  • 【Java】使用PowerMockito mock static方法/new对象/mock对象的public或private方法的简单示例

    1.1 打桩类的public static方法 测试用例中如果需要对public静态方法的打桩,针对测试类增加注解@RunWith(PowerMockRunner.class)同时针对静态方法所在的类增加注解@PrepareForTest({StaticMethod.class}),接着在测试用例调用方法之前增加 PowerMockito.mockStatic(StaticMethod.class); PowerMockito.when(StaticMet

    2024年01月24日
    浏览(41)
  • Mockito mock与spy的区别

    ##前言 Mockito是一个强大的mock工具,本文将重点讲述Mockito中mock与spy的区别 mock与spy的区别 mock跟spy都可以用于模拟对象,区别是mock产生的对象,并不会真正的执行对象的行为,而spy创建的对象,会真的去执行对象的行为 示例: 输出: 通过代码示例可以看出,对mockedList的操作

    2024年02月11日
    浏览(37)
  • Mockito无法Mock RedisTemplate解决方案

    如题,在SpringBoot工程中使用@MockBean对RedisTemplate进行Mock时发现报错,RedisTemplate连接工厂为null 当尝试将RedisConnectFaction注入测试类进行Mock后发现依然无效。 所以尝试新的解决方案: 将RedisTemplate使用@Spy注入原始类,在测试运行前对RedisTemplate底层方法进行批量Mock 经过测试后成功

    2024年02月12日
    浏览(54)
  • Android单元测试系列(3)-Mock之Mockito

    目录 一、官网 二、Demo示例 1. 目录结构 2. 被测试的类 3. 测试类 三、Mockito方法说明 1. mock对象创建 2. Mockito框架中的常见方法说明 2.1 常见的打桩方法 2.2 常见的验证行为 2.3 其他方法  3. Mockito的局限性 Mockito: https://github.com/mockito/mockito Mockito (Mockito 4.4.0 API) 为什么要用mock:

    2023年04月15日
    浏览(34)
  • mockito+junit 单元测试 测试私有方法利用反射去调用提升覆盖率 反射调用时传入参数为 null

    今天公司安排我写单元测试 因为要通过三级认证 公司要求是覆盖率必须达到100% 而在写单元测试的时候 对于是否要测试私有方法一直是一个争议 公司规范 对私有方法也进行测试 代码如下: JudgeUtils 是公司封装的一个工具类 让我们看看 isNull 方法的内部 代码如下: 我现在需

    2024年02月11日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包