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

java单元测试:编写可测试性好的代码

写出可测试性好的代码是编写高质量软件的关键。以下是一些有助于提高代码可测试性的最佳实践:

1. 单一职责原则 (Single Responsibility Principle)

每个类或方法应只负责一个功能。这样可以让测试更容易集中于单一功能。

2. 依赖注入 (Dependency Injection)

通过构造函数、方法参数或属性注入依赖,而不是在类内部创建依赖对象。这样可以在测试时轻松替换实际依赖为模拟对象。

3. 避免静态方法

静态方法难以进行单元测试,因为它们不能被替换或模拟。尽量使用实例方法。

4. 接口和抽象类

使用接口和抽象类来定义依赖的契约。这样可以轻松替换实现,方便测试。

5. 分离业务逻辑和外部依赖

将业务逻辑和外部依赖(如数据库、文件系统、网络等)分离。这样可以在测试时仅测试业务逻辑,而不依赖外部环境。

6. 小而专注的函数

函数应尽量小,并专注于完成一项任务。这样可以更容易编写测试,并且更容易发现和修复错误。

示例代码

以下是一个符合上述最佳实践的Java代码示例:

// 文件路径: src/main/java/com/example/service/UserService.javapackage com.example.service;import com.example.repository.UserRepository;
import com.example.model.User;public class UserService {private final UserRepository userRepository;// 通过构造函数注入依赖public UserService(UserRepository userRepository) {this.userRepository = userRepository;}public User getUserById(int userId) {return userRepository.findById(userId);}public void createUser(User user) {userRepository.save(user);}
}
// 文件路径: src/test/java/com/example/service/UserServiceTest.javapackage com.example.service;import com.example.repository.UserRepository;
import com.example.model.User;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;class UserServiceTest {private UserRepository userRepository;private UserService userService;@BeforeEachvoid setUp() {// 创建模拟对象userRepository = Mockito.mock(UserRepository.class);// 将模拟对象注入到被测试对象中userService = new UserService(userRepository);}@Testvoid testGetUserById() {// 设置模拟对象的行为User user = new User(1, "John Doe");when(userRepository.findById(1)).thenReturn(user);// 调用被测试方法User result = userService.getUserById(1);// 验证结果assertEquals(user, result);// 验证方法调用verify(userRepository).findById(1);}@Testvoid testCreateUser() {User user = new User(1, "John Doe");// 调用被测试方法userService.createUser(user);// 验证方法调用verify(userRepository).save(user);}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【机器学习论文阅读笔记】Robust Recovery of Subspace Structures by Low-Rank Representation
  • 嵌入式学习——3——域套接字UNIX
  • 如何在go语言中调用c语言代码
  • CTF-web-攻防世界-3
  • IT廉连看——UniApp——事件绑定
  • 使用FFmpeg推流实现在B站24小时点歌直播
  • 电路仿真软件:点亮教学新篇章,十大便利助力高效学习
  • -FIT5197
  • 基于Kafka的日志采集
  • ArcGIS提取含有计曲线的等高线
  • 设置环境变量,忽略yarn对node的版本检查
  • 行业分析---造车新势力之蔚来汽车
  • [力扣题解] 463. 岛屿的周长
  • 解释JAVA语言中关于方法的重载
  • JMeter正则表达式提取器和JSON提取器基础用法,小白必会!
  • HTTP--网络协议分层,http历史(二)
  • Java 9 被无情抛弃,Java 8 直接升级到 Java 10!!
  • JS数组方法汇总
  • laravel 用artisan创建自己的模板
  • Mysql优化
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • ViewService——一种保证客户端与服务端同步的方法
  • Vue.js源码(2):初探List Rendering
  • Wamp集成环境 添加PHP的新版本
  • Webpack 4 学习01(基础配置)
  • 对超线程几个不同角度的解释
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 面试总结JavaScript篇
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • 小程序开发之路(一)
  • 自制字幕遮挡器
  • Semaphore
  • # 利刃出鞘_Tomcat 核心原理解析(二)
  • #Datawhale AI夏令营第4期#多模态大模型复盘
  • #FPGA(基础知识)
  • #如何使用 Qt 5.6 在 Android 上启用 NFC
  • (1)Jupyter Notebook 下载及安装
  • (11)MSP430F5529 定时器B
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (Java企业 / 公司项目)点赞业务系统设计-批量查询点赞状态(二)
  • (二刷)代码随想录第15天|层序遍历 226.翻转二叉树 101.对称二叉树2
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (十七)Flink 容错机制
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (转) Android中ViewStub组件使用
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .Net 4.0并行库实用性演练
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .NET DataGridView数据绑定说明
  • .NET/C# 的字符串暂存池
  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • .NET+WPF 桌面快速启动工具 GeekDesk
  • .Net接口调试与案例
  • .NET开源项目介绍及资源推荐:数据持久层 (微软MVP写作)