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

三个要点,掌握Spring Boot单元测试

单元测试是软件开发中不可或缺的重要环节,它用于验证软件中最小可测试单元的准确性。结合运用Spring Boot、JUnit、Mockito和分层架构,开发人员可以更便捷地编写可靠、可测试且高质量的单元测试代码,确保软件的正确性和质量。

一、介绍

本文将从与单元测试相关的技术主题开始,在技术部分之后,介绍使用Spring Boot、JUnit和Mockito进行单元测试的实践。

二、测试的关键要素

1.单元

单元测试中的单元一词指的是软件中可以单独测试和处理的最小功能部分,通常是指函数、方法、类或模块等独立的代码片段。

2.用例

用例描述了系统使用特定功能或特性的方式,用于理解、设计和测试软件系统的需求。通常包括用户如何与系统进行交互、对系统的期望以及应该实现的结果等详细信息。

3.边界情况

边界情况指的是软件必须处理的特定场景,这些场景包括意外或边界条件,与典型情况有所不同或被认为是罕见的情况。边界情况可以包括意外用户登录、测试限制、异常输入或其他可能导致系统错误或异常行为的情况。在测试过程中,考虑和测试边界情况是非常重要的,因为它们可以帮助开发人员发现潜在的问题并确保系统的鲁棒性和稳定性。

三、单元测试

单元测试涵盖了我们可以考虑并编写的所有可能性。每个单元必须至少有一个测试方法。测试不是为一个方法编写的,而是为一个单元编写的。

可以按照以下顺序编写单元测试:正常路径/用例、边界情况和异常情况。

这些步骤是必不可少的,这样做可以确保单元以正确的方式处理输入,并生成预期的输出,展现出预期的行为。单元测试是及早发现风险和修复错误的最佳方式。通过单元测试,我们可以预防潜在的意外情况,应对生产代码的变更,确保生产代码能够处理各种情况。简而言之,单元测试确保了生产代码的安全性。

关于单元测试的另一个重要事项是要测试业务逻辑,不是在单元测试中测试基础设施代码,基础设施代码可以在集成测试中进行测试。可以考虑使用一些架构模式(如洋葱架构、六边形架构等)来将业务逻辑与基础设施代码分离。

单元测试的另一个优点是速度快,因为它不需要依赖 Spring ApplicationContext。由于上下文的原因,与单元测试相比,同一测试金字塔中的集成测试速度要慢得多。

1.开始编码

在分层架构项目中,业务代码主要位于服务层。这意味着服务层具有单元,需要进行测试。让我们聚焦于最关键的部分。

以下是一段示例代码:

  @Overridepublic String saveUser(User user) {validateUser(user);try {User savedUser = userRepository.save(user);return savedUser.getEmail();} catch (Exception exception) {throw new IllegalArgumentException(E_GENERAL_SYSTEM);}}private void validateUser(User user) {if (Objects.isNull(user.getEmail())) {throw new IllegalArgumentException(E_USER_EMAIL_MUST_NOT_BE_NULL);}if (findByEmail(user.getEmail()).isPresent()) {throw new IllegalArgumentException(E_USER_ALREADY_REGISTERED);}}@Overridepublic Optional<User> findByEmail(String email) {return userRepository.findByEmail(email);}

上述代码中有两个公共方法和一个私有方法,私有方法可以被视为公共方法的一部分。此外,由于代码的复杂性和功能需求,还存在许多可能的场景需要编写多个测试用例来覆盖各种情况,以确保代码的正确性。

2.注解

@ExtendWith用于将Mockito库集成到JUnit测试中。@Test 标记一个方法,使其成为一个测试方法,测试方法包含指定的测试用例,并由 JUnit 自动运行。

在测试过程中,需要模拟正在测试的类的依赖项。之前提到的原因是,由于 Spring ApplicationContext 不会启动,我们无法将依赖项注入到上下文中。@Mock 用于创建一个模拟的依赖项,而 @InjectMocks 则用于将这些模拟的依赖项注入到被测试类中。

@BeforeEach和@AfterEach可用于在每个方法运行之前和之后执行相应的操作。

@ParameterizedTest 用于使用不同的参数值运行重复的测试用例。通过使用 @ValueSource,可以为方法提供不同的参数值,以便进行多次测试。

3.测试方法的三个主要阶段

  • Given: 准备测试用例所需的对象
  • When: 执行必要的操作以运行测试场景
  • Then: 检查或验证预期结果

doReturn/when 用于确定在给定指定参数时方法的行为方式。但是,由于依赖项是 @Mock,并不会真正执行。

verify 用于检查被测试代码是否按照预期行为执行。如果要测试的方法是 public void 类型,可以使用 verify 进行验证。

断言用于验证预期结果。

 @ExtendWith(MockitoExtension.class)
class UserServiceImplTest {@InjectMocksprivate UserServiceImpl userService;@Mockprivate UserRepository userRepository;private User user;public static final String MOCK_EMAIL = "mert@bahardogan.com";@BeforeEachvoid setUp() {user = new User();System.out.println("init");}@AfterEachvoid teardown() {System.out.println("teardown");}@ParameterizedTest@ValueSource(strings = {"mert@bahardogan.com", "info@gmail.com"})@DisplayName("Happy Path: save user use cases")void givenCorrectUser_whenSaveUser_thenReturnUserEmail(String email) {// givenuser.setUserName("mertbahardogan").setEmail(email).setPassword("pass");User savedUser = new User().setEmail(email);doReturn(savedUser).when(userRepository).save(any());// whenString savedUserEmail = userService.saveUser(user);// thenverify(userRepository,times(1)).findByEmail(anyString());verify(userRepository,times(1)).save(any());assertEquals(email, savedUserEmail);}@Test@DisplayName("Exception Test: user email must not be null case")void givenNullUserEmail_whenSaveUser_thenThrowsEmailMustNotNullEx() {// whenException exception = assertThrows(IllegalArgumentException.class, () -> userService.saveUser(user));// thenassertNotNull(exception);assertEquals(E_USER_EMAIL_MUST_NOT_BE_NULL, exception.getMessage());}@Test@DisplayName("Exception Test: user is already registered case")void givenRegisteredUser_whenSaveUser_thenThrowsUserAlreadyRegisteredEx() {// givenuser.setEmail(MOCK_EMAIL);Optional<User> savedUser = Optional.of(new User().setEmail(MOCK_EMAIL));doReturn(savedUser).when(userRepository).findByEmail(anyString());// whenException exception = assertThrows(IllegalArgumentException.class, () -> userService.saveUser(user));// thenassertNotNull(exception);assertEquals(E_USER_ALREADY_REGISTERED, exception.getMessage());}@Test@DisplayName("Exception Test: catch case")void givenIncorrectDependencies_whenSaveUser_thenThrowsGeneralSystemEx() {// givenuser.setEmail(MOCK_EMAIL);// whenException exception = assertThrows(IllegalArgumentException.class, () -> userService.saveUser(user));// thenassertNotNull(exception);assertEquals(E_GENERAL_SYSTEM, exception.getMessage());}@Test@DisplayName("Happy Path: find user by email")void givenCorrectUser_whenFindByEmail_thenReturnUserEmail() {// givenOptional<User> savedUser = Optional.of(new User().setEmail(MOCK_EMAIL));doReturn(savedUser).when(userRepository).findByEmail(anyString());// whenOptional<User> user = userService.findByEmail(MOCK_EMAIL);// thenverify(userRepository,times(1)).findByEmail(anyString());assertEquals(savedUser, user);}
}

UserServiceImpl测试类运行时长为1秒693毫秒。

介绍一款软件开发工具

成功的前端工程师很会善用工具,这些年低代码概念开始流行,像国外的 Mendix,国内的 JNPF,这种新型的开发方式,图形化的拖拉拽配置界面,并兼容了自定义的组件、代码扩展,确实在 B 端后台管理类网站建设中很大程度上的提升了效率。

JNPF开发平台,很多人都用过它,它是功能的集大成者,任何信息化系统都可以基于它开发出来。

原理是将开发过程中某些重复出现的场景、流程,具象化成一个个组件、api、数据库接口,避免了重复造轮子。因而极大的提高了程序员的生产效率。

官网:http://www.jnpfsoft.com/?csdn,如果你有闲暇时间,可以做个知识拓展。

这是一个基于Java Boot/.Net Core构建的简单、跨平台快速开发框架。前后端封装了上千个常用类,方便扩展;集成了代码生成器,支持前后端业务代码生成,满足快速开发,提升工作效率;框架集成了表单、报表、图表、大屏等各种常用的Demo方便直接使用;后端框架支持Vue2、Vue3。

为了支撑更高技术要求的应用开发,从数据库建模、Web API构建到页面设计,与传统软件开发几乎没有差异,只是通过低代码可视化模式,减少了构建“增删改查”功能的重复劳动。

相关文章:

三个要点,掌握Spring Boot单元测试

单元测试是软件开发中不可或缺的重要环节&#xff0c;它用于验证软件中最小可测试单元的准确性。结合运用Spring Boot、JUnit、Mockito和分层架构&#xff0c;开发人员可以更便捷地编写可靠、可测试且高质量的单元测试代码&#xff0c;确保软件的正确性和质量。 一、介绍 本文…...

【nginx】Nginx配置:

文章目录 一、什么是Nginx&#xff1a;二、为什么使用Nginx&#xff1a;三、如何处理请求&#xff1a;四、什么是正向代理和反向代理&#xff1a;五、nginx 启动和关闭&#xff1a;六、目录结构&#xff1a;七、配置文件nginx.conf&#xff1a;八、location&#xff1a;九、单页…...

CSS3与HTML5

box-sizing content-box&#xff1a;默认&#xff0c;宽高包不含边框和内边距 border-box&#xff1a;也叫怪异盒子&#xff0c;宽高包含边框和内边距 动画&#xff1a;移动translate&#xff0c;旋转、transform等等 走马灯&#xff1a;利用动画实现animation&#xff1a;from…...

redis的简单使用

文章目录 环境安装与配置redis发布-订阅相关命令redis发布-订阅的客户端编程redis的订阅发布的例子 环境安装与配置 sudo apt-get install redis-server # ubuntu命令安装redis服务ubuntu通过上面命令安装完redis&#xff0c;会自动启动redis服务&#xff0c;通过ps命令确认&a…...

Windows下启动freeRDP并自适应远端桌面大小

几个二进制文件 xfreerdp # Linux下的&#xff0c;an X11 Remote Desktop Protocol (RDP) client which is part of the FreeRDP project wfreerdp.exe # Windows下的&#xff0c;freerdp2.0 主程序&#xff0c;freerdp3.0将废弃 sdl-freerdp.exe # Windows下的&…...

ES6中的数值扩展

1. 二进制和八进制的表示法 二进制和八进制的前缀分别为0b(或0B)和0o(或0O)表示 在ES5的严格模式下&#xff0c;八进制不再允许使用前缀0表示 如果要将0b和0x前缀的字符串数值转为十进制&#xff0c;要使用Number方法 Number(0b111); // 7 Number(0o10); // 82. Number.isF…...

自定义注解实现Redis分布式锁、手动控制事务和根据异常名字或内容限流的三合一的功能

自定义注解实现Redis分布式锁、手动控制事务和根据异常名字或内容限流的三合一的功能 文章目录 [toc] 1.依赖2.Redisson配置2.1单机模式配置2.2主从模式2.3集群模式2.4哨兵模式 3.实现3.1 RedisConfig3.2 自定义注解IdempotentManualCtrlTransLimiterAnno3.3自定义切面Idempote…...

Linux:minishell

目录 1.实现逻辑 2.代码及效果展示 1.打印字符串提示用户输入指令 2.父进程拆解指令 3.子进程执行指令,父进程等待结果 4.效果 3.实现过程中遇到的问题 1.打印字符串的时候不显示 2.多换了一行 3.cd路径无效 4.优化 1.ll指令 2.给文件或目录加上颜色 代码链接 模…...

STM32驱动步进电机

前言 &#xff08;1&#xff09;本章介绍用stm32驱动42步进电机&#xff0c;将介绍需要准备的硬件器材、所需芯片资源以及怎么编程及源代码等等。 &#xff08;2&#xff09;实验效果&#xff1a;按下按键&#xff0c;步进电机顺时针或逆时针旋转90度。 &#xff08;3&#xff…...

计算机视觉——飞桨深度学习实战-深度学习网络模型

深度学习网络模型的整体架构主要数据集、模型组网以及学习优化过程三部分&#xff0c;本章主要围绕着深度学习网络模型的算法架构、常见模型展开了详细介绍&#xff0c;从经典的深度学习网络模型以CNN、RNN为代表&#xff0c;到为了解决显存不足、实时性不够等问题的轻量化网络…...

用c动态数组(不用c++vector)实现手撸神经网咯230901

用c语言动态数组(不用c++的vector)实现:输入数据inputs = { {1, 1}, {0,0},{1, 0},{0,1} };目标数据targets={0,0,1,1}; 测试数据 inputs22 = { {1, 0}, {1,1},{0,1} }; 构建神经网络,例如:NeuralNetwork nn({ 2, 4,3,1 }); 则网络有四层、输入层2个nodes、输出层1个节点、第…...

视频讲解|基于DistFlow潮流的配电网故障重构代码

目录 1 主要内容 2 视频链接 1 主要内容 该视频为基于DistFlow潮流的配电网故障重构代码讲解内容&#xff0c;对应的资源下载链接为基于DistFlow潮流的配电网故障重构(输入任意线路)&#xff0c;对该程序进行了详尽的讲解&#xff0c;基本做到句句分析和讲解&#xff08;讲解…...

Ultralytics(YoloV8)开发环境配置,训练,模型转换,部署全流程测试记录

关键词&#xff1a;windows docker tensorRT Ultralytics YoloV8 配置开发环境的方法&#xff1a; 1.Windows的虚拟机上配置&#xff1a; Python3.10 使用Ultralytics 可以得到pt onnx&#xff0c;但无法转为engine&#xff0c;找不到GPU&#xff0c;手动转也不行&#xff0…...

springboot之@ImportResource:导入Spring配置文件~

ImportResource的作用是允许在Spring配置文件中导入其他的配置文件。通过使用ImportResource注解&#xff0c;可以将其他配置文件中定义的Bean定义导入到当前的配置文件中&#xff0c;从而实现配置文件的模块化和复用。这样可以方便地将不同的配置文件进行组合&#xff0c;提高…...

阿里云服务器免费申请入口_注册阿里云免费领4台服务器

注册阿里云账号&#xff0c;免费领云服务器&#xff0c;最高领取4台云服务器&#xff0c;每月750小时&#xff0c;3个月免费试用时长&#xff0c;可快速搭建网站/小程序&#xff0c;部署开发环境&#xff0c;开发多种企业应用。阿里云百科分享阿里云服务器免费领取入口、免费云…...

ES6中的async、await函数

async是为了解决异步操作&#xff0c;其实是一个语法糖&#xff0c;使代码书写更加简洁。 1. async介绍 async放在一个函数的前面&#xff0c;await则放在异步操作前面。async代表这个函数中有异步操作需要等待结果&#xff0c;在一个async函数中可以存在多个await&#xff0…...

代码随想录算法训练营第五十六天 | 动态规划 part 14 | 1143.最长公共子序列、1035.不相交的线、53. 最大子序和(dp)

目录 1143.最长公共子序列思路代码 1035.不相交的线思路代码 53. 最大子序和&#xff08;dp&#xff09;思路代码 1143.最长公共子序列 Leetcode 思路 本题和718. 最长重复子数组 区别在于这里不要求是连续的了&#xff0c;但要有相对顺序&#xff0c;即&#xff1a;“ace” …...

【数据挖掘】2021年 Quiz 1-3 整理 带答案

目录 Quiz 1Quiz 2Quiz 3Quiz 1 Problem 1 (30%). Consider the training data shown below. Here, A A A and B B B</...

【软件设计师-中级——刷题记录6(纯干货)】

目录 管道——过滤器软件体系结构风格优点&#xff1a;计算机英语重点词汇&#xff1a;单元测试主要检查模块的以下5个特征&#xff1a;数据库之并发控制中的事务&#xff1a;并发产生的问题解决方案:封锁协议原型化开发方法&#xff1a; 每日一言&#xff1a;持续更新中... 个…...

微信小程序点单左右联动的效果实现

微信小程序点单左右联动的效果实现 原理解析&#xff1a;   点击左边标签会跳到右边相应位置&#xff1a;点击改变rightCur值&#xff0c;转跳相应位置滑动右边&#xff0c;左边标签会跳到相应的位置&#xff1a;监听并且设置每个右边元素的top和bottom&#xff0c;再判断当…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

接口自动化测试:HttpRunner基础

相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具&#xff0c;支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议&#xff0c;涵盖接口测试、性能测试、数字体验监测等测试类型…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程

STM32F1 本教程使用零知标准板&#xff08;STM32F103RBT6&#xff09;通过I2C驱动ICM20948九轴传感器&#xff0c;实现姿态解算&#xff0c;并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化&#xff0c;适合嵌入式及物联网开发者。在基础驱动上新增…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...

字符串哈希+KMP

P10468 兔子与兔子 #include<bits/stdc.h> using namespace std; typedef unsigned long long ull; const int N 1000010; ull a[N], pw[N]; int n; ull gethash(int l, int r){return a[r] - a[l - 1] * pw[r - l 1]; } signed main(){ios::sync_with_stdio(false), …...

GAN模式奔溃的探讨论文综述(一)

简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...