当前位置: 首页 > article >正文

单元测试入门和mockup

Java 新手入门:Java单元测试利器,Mock详解_java mock-CSDN博客

这个是典型的before when assert三段式,学一下单测思路

 这个没有动态代理,所以是直接class(对比下面)

Jmockit使用笔记_增加代码覆盖率_覆盖try catch_使用new MockUp私有方法-CSDN博客

new mock up:

Jmockit使用@MockUp控制被注入Service的方法_mockup使用教程-CSDN博客

默认方法的含义

在 JMockit 中,当一个类的依赖(如 链接的UserService)被注入时,如果没有为该依赖的某个方法设置具体的行为,JMockit 会提供一个默认实现。这个默认实现通常是:

  1. 对于 返回值类型 的方法:
    • 返回值类型是 int 或其他基本类型时,返回其默认值(如 0false 等)。
    • 返回值类型是对象时,返回 null
  2. 对于 void 方法
    • 不执行任何实际逻辑,相当于一个空实现。

由于 userService 是被 JMockit 模拟的,setUserId 方法的默认实现 不会修改 orderInfouserId 属性。因此:

  • orderInfo.getUserId() 始终为 null

模拟类里面的方法:

方式一:使用new Expectations()

@Test
public void getOrderInfo1() {
    new Expectations() {{
        userService.setUserId((OrderInfo) any);
        result = new Delegate<OrderInfo>() {
            void delegate(OrderInfo orderInfo) {
                orderInfo.setUserId("ZHANGSAN123"); // 模拟方法逻辑
            }
        };
    }};

    OrderInfo result = testService.getOrderInfo("123");

    // 验证结果
    Assert.assertEquals("ZHANGSAN123", result.getUserId());
}

这部分代码是 JMockit 的 Expectations 定义,主要用来模拟依赖对象 userService 的行为。

  • userService.setUserId((OrderInfo) any)
    声明当 userServicesetUserId 方法被调用时,不管传入的参数是什么((OrderInfo) any),都会执行后续的行为。

  • result = new Delegate<OrderInfo>()
    为被调用的方法定义了一个代理逻辑(即模拟实现)。这里 Delegate 是 JMockit 提供的功能,用来自定义方法的执行逻辑。

  • 代理逻辑:void delegate(OrderInfo orderInfo)

    • 传入的 orderInfo 对象是调用 setUserId 方法时的参数。
    • 在代理逻辑中,直接对 orderInfouserId 属性赋值为 "ZHANGSAN123"

 

解读:
  • userService.setUserId((OrderInfo) any)
    定义了 userServicesetUserId 方法在接收到任何 OrderInfo 对象作为参数时,会执行以下逻辑。

  • result = new Delegate<OrderInfo>() { ... }
    通过 Delegate 为方法提供了具体的代理逻辑:

    • setUserId 被调用时,不会执行真实的实现,而是执行代理逻辑,直接将 orderInfo.userId 设置为 "ZHANGSAN123"
Expectations 如何影响依赖对象?
示例:

OrderInfo result = testService.getOrderInfo("123");

  1. 依赖方法调用

    • testService.getOrderInfo 会调用 userService.setUserId(orderInfo)
  2. 方法替换

    • 因为用 Expectations 模拟了 setUserId 方法,实际调用的不是 UserService 的真实方法,而是 Expectations 中定义的代理逻辑。
  3. 逻辑执行

    • 在代理逻辑中,将 orderInfo.userId 设置为 "ZHANGSAN123"
  4. 结果返回

    • 通过修改后的 OrderInfo 对象返回给调用方。

基本原理
Expectations 是 JMockit 提供的一种基于 声明式 的方式,用于定义某个依赖对象的方法行为。

  • 通过在测试代码中定义具体的行为,测试框架根据定义的规则动态返回结果或执行逻辑。
  • 对特定实例生效,不影响该类的其他实例。

 

方式2:使用new mockup()推荐:更easy

new MockUp<UserService>(userService.getClass()) {
    @Mock
    public void setUserId(OrderInfo orderInfo) {
        orderInfo.setUserId("zhangsan123");
    }
};

基本原理
MockUp 是 JMockit 提供的一种方式,用于在运行时修改类的方法实现。

  • 可以直接为某个类的具体方法编写新的实现,类似于 重写方法。
  • 使用 @Mock 注解标记需要模拟的方法。

 注意:

/**
 * @author xinruoxiangyang9010
 * 这里的参数必须是:userService.getClass()
 * 如果写成UserService.class则@Mock里面的方法不生效
 */
new MockUp<UserService>(userService.getClass())
   
1. UserService.class
  • 表示类级别的代理
    当你使用 new MockUp<UserService>()new MockUp<UserService>(UserService.class) 时,JMockit 会针对 UserService 类本身 进行代理。
    • 它的效果是全局生效,影响所有实例。
    • 但是,如果在运行时,你注入的是 userService 的一个动态代理对象(比如 Spring 的动态代理机制生成的对象),代理逻辑不会直接生效。
2. userService.getClass()
  • 表示对象所属的动态类型
    userService.getClass() 返回的是 userService 实际运行时的类型。
    • 如果 userService 是被 Spring 动态代理(如 CGLIB 或 JDK 动态代理)生成的对象,那么 userService.getClass() 返回的就是这个动态代理类。
    • MockUp 会针对这个动态代理类生效,从而让 @Mock 标注的方法在调用时起作用。

在实际项目中,特别是使用 Spring 框架时,@Autowired 注入的 userService 很可能是一个动态代理对象,而不是直接的 UserService 实例。 

假设 userService 是通过 Spring 注入的动态代理对象: 

System.out.println(userService.getClass()); // 输出类似 com.example.UserService$$EnhancerBySpringCGLIB$$12345

 

 

 


http://www.kler.cn/a/463616.html

相关文章:

  • canvas+fabric实现时间刻度尺+长方形数据展示
  • 数据库知识汇总2
  • Hive之import和export使用详解
  • 《HarmonyOS第一课》焕新升级,赋能开发者快速掌握鸿蒙应用开发
  • C# 设计模式(结构型模式):适配器模式
  • 加强版第二十章基于颜色的对象跟踪
  • ruoyi 分页 查询超出后还有数据; Mybatis-Plus 分页 超出后还有数据
  • 常见CMS漏洞(wordpress,DedeCms,ASPCMS,PHPMyAdmin)
  • MATLAB 中打印某些变量的值到文本文件中,使用diary和 fprintf
  • 人工智能:变革时代的核心驱动力
  • 阿里云redis内存优化——PCP数据清理
  • 华为开源自研AI框架昇思MindSpore应用案例:ICNet用于实时的语义分割
  • C# 将图片转换为PDF文档
  • 虹安信息技术有限公司数据泄露防护平台pushSetup存在SQL注入漏洞
  • 【Elasticsearch入门到落地】5、安装IK分词器
  • [最佳方法] 如何将视频从 Android 发送到 iPhone
  • Windows操作系统部署Tomcat详细讲解
  • LeetCode 3280.将日期转换为二进制表示:库函数实现或手动转换
  • 力扣第129题:求根到叶子节点数字之和 - C语言解法
  • 报错:nginx [emerg] open() etcnginxnginx.conf failed (2 No such file or directory)
  • 【网络协议】开放式最短路径优先协议OSPF详解(一)
  • WebRTC的三大线程
  • 设计模式の状态策略责任链模式
  • 【漫话机器学习系列】027.混淆矩阵(confusion matrix)
  • 计算机网络•自顶向下方法:DHCP、NAT、IPV6
  • 大模型WebUI:Gradio全解系列8——Additional Features:补充特性(下)