单体测试Junit

news2025/1/19 8:01:43

 

 本来是想要查找关于junit 的知识,查找了依赖注入方式不同对junit测试也有影响。

正好备注下。

依赖注入三种方式:

       字段注入(@Autowird)

               优点: 

                          操作简单
                          代码简洁

               缺点: 

                         不支持不可变性:不能用final

                         容易出现依赖循环:程序刚启动时不报错

                         在单元测试中,很难替换依赖项

       构造方法注入  

               优点:

                        不可变性:注入对象不可被修改

                        避免出现循环依赖

                        非IOC框架代码通用

              缺点: 

                        多依赖,代码阅读,维护困难

                        

       Setter 注入

         ---------------

       

Junit  测试

添加依赖    

        <!-- 包含了JUnit 5测试框架的核心API和注解-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <scope>test</scope>
        </dependency>
        <!--Spring Boot提供的用于测试的启动器依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
       <!--提供参数化测试-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.7.2</version>
            <scope>test</scope>
        </dependency>

快捷创建测试接口

      以岗位信息接口为例:

     鼠标右击->生成->测试->选择测试接口

      

在同模块下的测试工程快捷自动生成测试类

  查看service层代码,考虑几个测试场景:

  1. 当数据库中不存在相同的岗位名称时,期望返回UserConstants.UNIQUE
  2. 当数据库中存在相同的岗位名称但是岗位ID与当前岗位ID不同,期望返回UserConstants.NOT_UNIQUE
  3. 当数据库中存在相同的岗位名称且岗位ID与当前岗位ID相同时,期望返回UserConstants.UNIQUE
    /**
     * 校验岗位名称是否唯一
     * 
     * @param post 岗位信息
     * @return 结果
     */
    @Override
    public boolean checkPostNameUnique(SysPost post)
    {
        Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId();
        SysPost info = postMapper.checkPostNameUnique(post.getPostName());
        if (StringUtils.isNotNull(info) && info.getPostId().longValue() != postId.longValue())
        {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

 编写测试代码

测试应遵循BDD三段式:given、when、then;即:假设xxx……那么当yyy时……应该会zzz。

package com.ruoyi.system.service.impl;

import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.mapper.SysPostMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
public class SysPostServiceImplTest {

    @Mock
    private SysPostMapper postMapper;

    @InjectMocks
    private SysPostServiceImpl postService;


  
    @BeforeEach
    void setUp() {}

    /**
     * 当数据库中不存在相同的岗位名称时,应返回UNIQUE
     */
    @Test
    @DisplayName("NotExistingName")
    public void testCheckPostNameUnique_NotExistingName() {
        SysPost post = new SysPost();
        post.setPostId(1L);
        post.setPostName("Test Post");

        when(postMapper.checkPostNameUnique("Test Post")).thenReturn(null);

        Assertions.assertEquals(UserConstants.UNIQUE, postService.checkPostNameUnique(post));
    }

    /**
     * 当数据库中存在相同的岗位名称但是岗位ID不同时,应返回NOT_UNIQUE
     */
    @Test
    @DisplayName("ExistingNameDifferentId")
    public void testCheckPostNameUnique_ExistingNameDifferentId() {
        SysPost existingPost = new SysPost();
        existingPost.setPostId(2L);
        existingPost.setPostName("Test Post");

        SysPost post = new SysPost();
        post.setPostId(1L);
        post.setPostName("Test Post");

        when(postMapper.checkPostNameUnique("Test Post")).thenReturn(existingPost);

        Assertions.assertEquals(UserConstants.NOT_UNIQUE, postService.checkPostNameUnique(post));
    }

    /**
     * 当数据库中存在相同的岗位名称且岗位ID相同时,应返回UNIQUE
     */
    @Test
    @DisplayName("ExistingNameSameId")
    public void testCheckPostNameUnique_ExistingNameSameId() {
        SysPost existingPost = new SysPost();
        existingPost.setPostId(1L);
        existingPost.setPostName("Test Post");

        SysPost post = new SysPost();
        post.setPostId(1L);
        post.setPostName("Test Post");

        when(postMapper.checkPostNameUnique("Test Post")).thenReturn(existingPost);

        Assertions.assertEquals(UserConstants.UNIQUE, postService.checkPostNameUnique(post));
    }
}

测试case

运行代码

 测试成功后,右下角可以查看case的覆盖情况

左侧绿色表示测试覆盖成功,红色表示未测试或case覆盖不完全

右侧可查看测试类的覆盖率

 生成测试报告

 

 

 

参数化测试

提供灵活的参数测试。

可以一个测试case灵活设置多个不同参数,表示不同参数。大大减少了测试代码量。

JUnit5参数化测试的几种方式-CSDN博客

@CsvSource注解中的每一行代表一个测试用例。

第一个参数是岗位名称。

第二个参数的岗位id。

第三个参数是预期的唯一性状态。

    @ParameterizedTest
    @CsvSource({
            "UniquePostName,1, true",
            "ExistingPostName,2 ,false",
            "UniquePostName,2, true"
    })
    @DisplayName("Should return correct uniqueness status")
    public void testCheckPostNameUnique(ArgumentsAccessor arguments) {
        String postName = arguments.getString(0);
        Long postId = arguments.getLong(1);
        boolean expectedStatus = arguments.getBoolean(2);
        // 模拟postMapper的行为
        if ("UniquePostName".equals(postName)) {
            when(postMapper.checkPostNameUnique(postName)).thenReturn(null);
        } else if ("ExistingPostName".equals(postName)) {
            SysPost existingPost = new SysPost();
            existingPost.setPostId(1L);
            when(postMapper.checkPostNameUnique("ExistingPostName")).thenReturn(existingPost);
        } else {
            when(postMapper.checkPostNameUnique(null)).thenReturn(null);
        }

        SysPost post = new SysPost();
        post.setPostName(postName);
        post.setPostId(postId);
        assertEquals(expectedStatus, postService.checkPostNameUnique(post));
    }

 实现一个case满足三种情况

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1682353.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java面试八股之HashMap和HashTable有什么区别

Java中HashMap和HashTable有什么区别 线程安全性&#xff1a; HashMap&#xff1a;非线程安全。在多线程环境下&#xff0c;如果没有采取适当的同步措施&#xff0c;直接并发访问可能会导致数据不一致、死锁等问题。如果需要在多线程环境中安全地使用HashMap&#xff0c;通常…

【FFmpeg】Filter 过滤器 ② ( 裁剪过滤器 Crop Filter | 裁剪过滤器语法 | 裁剪过滤器内置变量 | 裁剪过滤器常用用法 )

文章目录 一、裁剪过滤器1、裁剪过滤器简介2、裁剪过滤器语法3、裁剪过滤器内置变量4、裁剪过滤器示例5、裁剪过滤器应用6、裁剪过滤器图示 二、裁剪过滤器常用用法1、裁剪指定像素的视频区域2、裁剪视频区域中心正方形 - 默认裁剪3、裁剪视频区域中心正方形 - 手动计算4、裁剪…

STM32程序下载电路设计

一、背景介绍 使用STM32F103RCT6作为单片机主控芯片&#xff0c;在进行电路板设计过程中&#xff0c;需要预留程序下载接口&#xff0c;可以选择使用JLINK下载器下载程序。 二、设计过程 1、查看STM32F103RCT6的芯片手册&#xff0c;找到下载程序的引脚端口PA13和PA14&#x…

使用WPF中的Trigger实现按钮样式动态更改

使用WPF中的Trigger实现按钮样式动态更改 在Windows Presentation Foundation (WPF)中&#xff0c;Trigger 是一种强大的机制&#xff0c;它可以基于控件的属性值来动态更改控件的样式。这篇博客将介绍如何使用Trigger实现按钮在鼠标悬停时样式动态更改的效果。我们将详细讨论为…

自然语言处理通用框架BERT原理解读

相关代码见文末 1.概述 问题背景: 传统Seq2Seq模型的局限性: 早期的机器翻译和文本生成任务常采用基于循环神经网络(RNN)的序列到序列(Seq2Seq)模型,这类模型在处理长序列时容易遇到梯度消失/爆炸问题,导致训练效率低,难以捕捉长期依赖。 RNN网络的问题: RNN及其变…

基于vs和C#的WPF应用之动画4---跳跳球

一、画布和图形 <Canvas x:Name"canvas4" Grid.Row"1" Grid.Column"1" Width"200" Height"200"><Canvas.Triggers><EventTrigger RoutedEvent"Loaded"><BeginStoryboard Storyboard"…

牛客热题:合并二叉树

牛客热题&#xff1a;二叉树与双向链表> &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题…

TypeScript基础知识:TypeScript是什么?为什么会出现TypeScript?TypeScript相较于javascript有那些优势?

TypeScript(简称:TS)是JavaScript的超集(JS有的TS 都有)。 图解就是&#xff1a; TypeScriptType javaScript(在JS 基础之上&#xff0c;为JS 添加了类型支持)。 TypeScript 是微软开发的开源编程语言&#xff0c;可以在任何运行JavaScript的地方运行。 那么为什么要出现type…

CPT7数据保存详细步骤

一、连接设备、打开NovAtelConnect 软件 (1)点击1,并在2中输入如下命令: LOG RANGEB ONTIME 1 // 输出原始数据记录在板卡LOG RAWEPHEMB ONTIME 1 // 输出 GPS 原始星历记录在板卡LOG bdsephemerisb ONTIME 1 // 输出

VMware17.5与Ubuntu22.04虚拟机环境搭建

VMware17.5安装教程也有参考此链接 简介 Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和Unix的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的Unix工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设…

一文读懂deepSpeed:深度学习训练的并行化

引言 在深度学习领域&#xff0c;模型训练的过程不仅资源密集&#xff0c;而且技术复杂。近年来&#xff0c;随着模型规模和数据量的不断增长&#xff0c;深度学习训练面临着越来越多的挑战。这些挑战主要体现在计算资源的需求、训练效率、模型复杂度以及内存管理等多个方面。…

32位处理的寻址方式

32位处理器兼容16位处理器的寻址方式&#xff0c;可以运行传统的16位代码。但是由于32位的处理器都拥有32位的寄存器和算数逻辑部件&#xff0c;而且同内存芯片之间的数据通路至少是32位的&#xff0c;因此&#xff0c;所有需要从寄存器或者内存地址处取得操作数的指令都被扩充…

直播卖券有妙招:实景ai无人直播系统帮助商家自动化团购直播!

在数字化浪潮席卷的今天&#xff0c;直播卖券已成为商家推广和营销的重要手段。然而&#xff0c;如何高效、精准地利用直播卖券&#xff0c;让每一位观众都能沉浸在购物的乐趣中&#xff0c;成为商家们迫切需要解决的问题。幸运的是&#xff0c;实景AI无人直播系统应运而生&…

升级GPT 4.0 会员,到底值不值?

对于这个问题&#xff0c;我的回答是&#xff1a;不太值得&#xff01;并不是4.0不好用&#xff0c;这价格稍微贵了点儿。 这么贵&#xff0c;这谁顶的住啊&#xff1f;好用是好用&#xff0c;但是没必要。 我的使用心得 我是怎么用的呢&#xff1f;我先用3.5版本问问题&…

使用 ONNX Runtime 在 iPhone 上运行 Phi-3-mini

更多科技分享&#xff0c;请关注公众号&#xff1a;ONE生产力 之前我们介绍了微软最新开源的小规模模型Phi-3-mini&#xff0c;其计算资源占用极少&#xff0c;非常适合嵌入式应用和移动智能终端。今天我们将探讨在iPhone上&#xff0c;通过ONNX Runtime运行Phi-3-mini模型。 …

教你五行代码实现大批量文件重命名

问题背景 文件夹里的大量文件&#xff0c;命名很乱&#xff0c;并且要重新命名为固定长度顺序的文件很麻烦。这里采用5行python实现大批量文件按要求统一命名。 现有文件夹列表 tulips 代码实现 main.py import os path rtulips/ for num, file in enumerate(os.listdir(…

unity制作app(7)--panel control

根据用户的状态&#xff0c;在界面中显示不同的panel 1.新建一个脚本PanelControl&#xff0c;控制各个脚本的显示与隐藏 2.实现第一个逻辑判断功能&#xff1a;如果没有登记过信息&#xff0c;就直接跳转到登记界面&#xff0c;如果登记过&#xff0c;跳转到住界面。许多需要…

apifox接口调试工具的使用,代替postman

官网链接&#xff1a;Apifox &#xff08;代替postman工具&#xff09; 下载apifox工具 使用步骤 安装本地下载的apifox.exx 登录apifox 接口调用

DDNS配置详解

正文共&#xff1a;1111 字 8 图&#xff0c;预估阅读时间&#xff1a;1 分钟 前面配置了DDNS&#xff08;拨号有公网IP地址了&#xff0c;肯定要通过DDNS用起来啊&#xff01;&#xff09;&#xff0c;有不少小伙伴咨询具体的配置问题。为了方便大家深入理解DDNS的技术原理&am…

翻译《The Old New Thing》- Stupid debugger tricks: Calling functions and methods

Stupid debugger tricks: Calling functions and methods - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20070427-00/?p27083 Raymond Chen 2007年04月27日 一个比较笨的调试技巧&#xff1a;调用函数和方法 在过去&#xff0c;如果你想在…