【JAVA】单元测试的简单应用

单元测试是验证软件中最小可测试部分正确性的自动化测试。在Java中,单元测试通常针对类的方法或函数进行。以下是单元测试的一般写法,以及一些常用的单元测试框架。

1. 准备工作

在开始编写单元测试之前,需要确保项目中包含了单元测试框架。Java中常用的单元测试框架有:

  • JUnit: 最流行的Java单元测试框架。
  • TestNG: 功能强大的测试框架,与JUnit兼容但提供了更多特性。
  • Mockito: 主要用于模拟对象和行为的工具。

2. 创建测试类

测试类通常放在与源代码相同的包中,但位于不同的源集(source set)里。测试类的命名约定通常是在被测试类名后加上"Test"后缀。

3. 编写测试方法

测试方法通常遵循以下命名约定:test + 方法描述,必须使用public访问修饰符,并且是void返回类型。JUnit 4使用注解@Test来标识测试方法。

4. 断言(Assertions)

断言是单元测试中的核心,用于验证代码的预期输出。JUnit提供了多种断言方法,如:

  • assertEquals: 验证两个值是否相等。
  • assertTrue: 验证一个条件是否为真。
  • assertFalse: 验证一个条件是否为假。
  • assertNotNull: 验证对象不为null。
  • assertNull: 验证对象为null。

示例:使用JUnit 4编写单元测试

假设我们有以下简单的加法类:

public class Calculator {public int add(int a, int b) {return a + b;}
}

对应的单元测试可能如下:

import static org.junit.Assert.assertEquals;
import org.junit.Test;public class CalculatorTest {@Testpublic void testAdd() {Calculator calculator = new Calculator();assertEquals("10 + 5 must equal 15", 15, calculator.add(10, 5));}@Testpublic void testAddZero() {Calculator calculator = new Calculator();assertEquals("Adding zero must return the same number", 5, calculator.add(5, 0));}@Test(expected = IllegalArgumentException.class)public void testAddNegative() {Calculator calculator = new Calculator();calculator.add(-1, 5);}
}

使用Mockito进行单元测试

当测试涉及与其他对象交互或需要模拟外部依赖时,可以使用Mockito来创建模拟对象。

import static org.mockito.Mockito.*;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;public class ServiceTest {@Mockprivate Dependency dependency;@Beforepublic void setUp() {MockitoAnnotations.initMocks(this);}@Testpublic void testSomeBehavior() {Service service = new Service(dependency);// 设置模拟行为when(dependency.someMethod()).thenReturn("expected value");// 执行测试String result = service.someBehavior();// 验证方法调用verify(dependency).someMethod();// 断言结果assertEquals("Method should return expected value", "expected value", result);}
}

实例1:验证方法调用

假设我们有一个UserService类,它依赖于一个UserRepository接口来获取用户信息。

public interface UserRepository {User findUserById(int id);
}public class UserService {private final UserRepository userRepository;public UserService(UserRepository userRepository) {this.userRepository = userRepository;}public User getUser(int id) {return userRepository.findUserById(id);}
}

 

单元测试使用Mockito验证getUser方法是否正确调用了UserRepositoryfindUserById方法。

import static org.mockito.Mockito.*;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;public class UserServiceTest {@Mockprivate UserRepository userRepository;private UserService userService;@Beforepublic void setUp() {MockitoAnnotations.initMocks(this);userService = new UserService(userRepository);}@Testpublic void testGetUser() {User expectedUser = new User(1, "John Doe");when(userRepository.findUserById(anyInt())).thenReturn(expectedUser);User user = userService.getUser(1);verify(userRepository).findUserById(1);assertEquals("The returned user should be the expected user", expectedUser, user);}
}

实例2:测试异常处理

假设UserRepositoryfindUserById方法可能抛出一个自定义异常UserNotFoundException

public class UserNotFoundException extends Exception {public UserNotFoundException(int id) {super("User with id " + id + " not found.");}
}// UserService类保持不变

单元测试验证当用户未找到时,UserService是否正确地将异常传递出去。

@Test(expected = UserNotFoundException.class)
public void testGetUserWhenUserNotFound() {when(userRepository.findUserById(anyInt())).thenThrow(new UserNotFoundException(1));userService.getUser(1);
}

实例3:使用Mockito验证顺序

假设OrderService类需要按照特定的顺序调用两个依赖项PaymentServiceEmailService

public class OrderService {private final PaymentService paymentService;private final EmailService emailService;public OrderService(PaymentService paymentService, EmailService emailService) {this.paymentService = paymentService;this.emailService = emailService;}public void processOrder(Order order) {paymentService.processPayment(order);emailService.sendConfirmationEmail(order);}
}

单元测试验证processOrder方法中服务的调用顺序。

import static org.mockito.Mockito.*;@Test
public void testProcessOrder() {@MockPaymentService paymentService;@MockEmailService emailService;OrderService orderService = new OrderService(paymentService, emailService);Order order = new Order();orderService.processOrder(order);verify(paymentService).processPayment(order);verify(emailService).sendConfirmationEmail(order);// 验证调用顺序verify(paymentService, Mockito.ordering()).processPayment(order);verify(emailService, Mockito.ordering()).sendConfirmationEmail(order);
}

实例4:使用Spy进行部分模拟

假设我们想测试NetworkService类的真实行为,但同时要模拟一个方法。

public class NetworkService {public String sendRequest(String url) {// 实际发送网络请求的代码return "response";}
}

单元测试中,我们使用Spy来模拟sendRequest方法,而其他方法则使用真实实现。

@Test
public void testNetworkService() {NetworkService spyService = Mockito.spy(new NetworkService());doReturn("mocked response").when(spyService).sendRequest(anyString());String response = spyService.sendRequest("http://example.com");assertEquals("The response should be mocked", "mocked response", response);// 验证sendRequest是否被调用一次verify(spyService).sendRequest("http://example.com");
}

注意事项

  • 测试应该独立于彼此运行,不依赖于外部资源如数据库或网络服务。
  • 测试应该快速执行,以便频繁运行。
  • 测试代码应该具有可读性,易于理解。
  • 测试覆盖率是一个有用的指标,但100%的覆盖率并不总是必要的或最佳的。

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

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

相关文章

元组(tuple)

1. 区别 和列表相似,本质上是一种有序的集合元组和列表的不同之处: a.列表:[ ] 元组:( ) b.列表中的元素可以进行增加和删除操作;但是,元组中的元素不能修改【元素:一旦被初始化,将不能发生改…

prompt工程策略(三:使用 LLM 防护围栏创建系统提示)

原文:我是如何赢得GPT-4提示工程大赛冠军的 原文的原文: How I Won Singapore’s GPT-4 Prompt Engineering Competition !!本内容仅适用于具有 System Prompt(系统提示)功能的 LLM。具有这一功能的最著名 …

python dbUtil

# -*- coding: utf-8 -*- import pyodbc import cx_Oracleclass Database:def __init__(self, driver, server, database, username, password):"""链接数据库:param driver: 数据库驱动:param server: 地址:端口:param database: 数据库名称:param usernam…

工业无风扇计算机的优点

无风扇计算机往往采用紧凑且密封的外形,使其坚固耐用,使其能够在需要现场工程师进行维护之前承受恶劣的环境数年。机载移动部件较少或没有移动部件会降低组件无法按预期运行的可能性,或者更糟糕的是发生故障和损坏。采用工业组件和较低的散热…

您的文件和驱动器上的“密码保护”有多安全?

某些行业(例如医疗保健、法律和公司)的人们在通过电子邮件发送文件时通常依赖密码保护,认为它可以提供足够的安全性来防止窥探。然而,对 PDF 或 Excel 文件进行简单的密码保护并不像看起来那样万无一失。 使用密码保护文件而不加…

亿级流量系统架构设计与实战

💂 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】🤟 一站式轻松构建小程序、Web网站、移动应用:👉注册地址🤟 基于Web端打造的:👉轻量化工具创作平台💅 想寻找共同学习交…

Oracle Exists、 NOT Exists用法

Exists 在Oracle数据库中,EXISTS关键字用于子查询中,其主要用途是检查子查询是否至少返回了一行数据。它不关心子查询返回的实际数据值,只关心是否有结果。EXISTS通常用于基于行的存在性测试,相比IN或JOIN等操作,它在某…

自定义扩展文件支持

遇到问题加QQ群聊 群主在线解答 点击加入群聊【星辰开发】 Redis pip install redisdef get_conn():from redis import Redisfrom configparser import ConfigParserconfig ConfigParser()config.read(Config.ini)Redis_Host config[Redis][Host]Redis_Port config[Redis]…

Spring AI开发前期开发指导(maven依赖下载问题解决)

文章目录 说明开发条件网络环境准备本地环境准备开发工具准备 特殊说明maven配置项目jar一致下载错误解决可行的版本搭配 说明 动力节点视频教程地址,本文章学习该教程,同时说明的maven配置问题导致的项目依赖下载失败的问题和其他问题的记录。 开发条…

nginx-rtmp

1.已经安装nginx;configure配置模块;make编译无需安装;把objs/nginx复制到已安装的宁目录下 ./configure --prefix/usr/local/nginx --add-module/usr/local/src/fastdfs-nginx-module/src --add-module/usr/local/src/nginx-rtmp-module-mas…

浅谈SiC MOSFET之双脉冲原理

1.双脉冲实验实验的必要性 在平常的使用中,我们基本通过芯片手册来了解功率器件的各种性能参数,但是手册中的参数的测量环境都是在理想状态下,与实际使用或多或少都会有差别。通过双脉冲实验可以获取器件在真实工况下的参数,对于产…

Runes 生态一周要览 ▣ 2024.5.06-5.12

1、香港「Runes Asia 2024」符文峰会之行圆满结束。 2、BEVM 宣布首次大规模 RUNES 空投现已结束!符文桥即将上线。 3、来自 Book of Blob 的交互式视听信息铭刻了第一个 Epic Sat 在 coinex 上市交易。 4、 Binance Research 发布了对 Runes 的报告。 5、HOPE•…

redis报错500

之前自己举一反三把value也给序列化了: 然后报错了: 原因是这里传入的是Integer类型,序列化的话就变为string类型了

Android Studio 查看打开Room数据库数据

关于作者: CSDN内容合伙人、技术专家, 从零开始做日活千万级APP,带领团队单日营收超千万。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、商业化变现、人工智能等,希望大家多多支持。 目录 一、导读二、概览…

前端面试1-15

说一说JS变量提升? 函数和var声明的变量会有变量提升,js在预编译阶段会将函数和var声明的变量提升至最前面先执行,之后再按顺序执行代码块进行赋值,而let和const声明的变量只是创建提升,在预编译中将其创建&#xff0…

漏桶算法:稳定处理大量突发流量的秘密武器!

漏桶算法的介绍 我们经常会遇到这样一种情况:数据包的发送速率不稳定,而网络的带宽有限。如果在短时间内有大量的数据包涌入,那么网络就会出现拥塞,数据包的丢失率就会增大。为了解决这个问题,人们提出了一种叫做“漏…

lerna实战(一)

前言 将大型代码仓库分割成多个独立版本化的 软件包(package)对于代码共享来说非常有用。但是,如果某些更改 跨越了多个代码仓库的话将变得很 麻烦 并且难以跟踪,并且, 跨越多个代码仓库的测试将迅速变得非常复杂。 …

ai语音机器人智能电销机器人具体功能及工作流程

ai语音电销机器人智能,代替的主要是电话销售人员电话筛选客户的工作。因为电话销售人员每天90%的时间都是用在了拨打电话找客户上了。像这类简单、重复性的工作是完全可以由机器人取代的,我们一起来看看电销机器人的工作流程: 1、一键导入要…

Spring MVC 介绍及其使用(详细)

目录 一.什么是SpringMVC呢? 1.1MVC的介绍 1.2SpringMVC和MVC的关系 二.SpringMVC的学习 第一步:创建项目 第二步,SpringMVC的连接 第三步,Spring MVC获取参数 第四步 SpringMVC的输出 总结 特点和优势 核心组件 一.什…

发布一个属于自己的 npm工具包

我们可以发布一个属于自己的工具包到 npm 服务上,方便自己和其他开发者使用,参与社区贡献,操作步骤如下: 创建与发布 npm 初始化工具包,package.json 填写包的信息 (包的名字是唯一的)注册账号 https://www.npmjs.co…