Spcok测试代码抛异常场景
测试代码抛异常场景
`class ExceptionSpec extends Specification {def validateService = new ValidateService()@Unrolldef "验证UserInfo"() {when: "调用校验方法"validateService.validateUser(user)then: "捕获异常并设置需要验证的异常值"def exception = thrown(expectedException)exception.errorCode == expectedErrCodeexception.errorMessage == expectedMessagewhere: "验证用户的合法性"user || expectedException | expectedErrCode | expectedMessagenull || APIException | "1001" | "userInfo is null"new UserInfo(0, "") || APIException | "1002" | "id is not legal"new UserInfo(1, "") || APIException | "1003" | "name is not legal"}
}`
Spock内置thrown()方法,可以捕获调用业务代码抛出的预期异常并验证,再结合where表格的功能,可以很方便的覆盖多种自定义业务异常。
在then
标签里用到了Spock的thrown()
方法,这个方法可以捕获我们要测试的业务代码里抛出的异常。thrown()
方法的入参expectedException
,是我们自己定义的异常变量,这个变量放在where
标签里就可以实现验证多种异常情况的功能。expectedException
类型调用validateUser
方法里定义的APIException
异常,可以验证它所有的属性,errorCode
、errorMessage
是否符合预期值。
注意事项
在Spock中,异常条件(如thrown
和notThrown
)只能在then
块的顶层使用,不能嵌套在其他控制结构(如if
语句)中。这意味着你不能在if
语句内部使用thrown
方法。
为了测试不同输入数据下的方法行为,包括抛出异常和不抛出异常的情况,你需要将这些测试拆分为单独的测试用例。每个测试用例只测试一种情况:要么是抛出异常,要么是不抛出异常。
测试案例代码
// 测试捕获异常 RuntimeException 异常def "checkUrlThrowException"() {given:SSRFUtilwhen:SSRFUtil.checkUrl(requestUrl)then:def exception = thrown(expectedException)where:requestUrl || expectedException"https://baidu.com" || RuntimeException}// 测试不抛异常def "checkUrlNotException"() {given:SSRFUtilwhen:SSRFUtil.checkUrl(requestUrl)then:def exception = notThrown(expectedException)where:requestUrl || expectedException"https://xxx.aaa.com/xxx/xxxx.xlsx" || null"https://xxx.aaa.net/xxx/xxxx.xlsx" || null"https://xxx.vip.aaa.com/xxx/xxxx.xlsx" || null}
其它
下面的案例来自于 小美智能助理 的答案.
在Spock中,where
块用于数据驱动测试,通过提供多个输入数据集来测试方法的行为。在测试方法不抛出异常的情况下,可以在then
块中使用notThrown
方法来验证没有异常被抛出。你可以结合where
块和notThrown
方法来测试方法在不同输入数据下的行为。
以下是一个示例,展示了如何在where
块中测试方法在不同输入数据下不抛出异常的情况。
示例代码
假设你有一个Calculator
类,它的divide
方法在除以零时会抛出一个IllegalArgumentException
,在其他情况下正常工作。
class Calculator {int divide(int a, int b) {if (b == 0) {throw new IllegalArgumentException("Division by zero")}return a / b}
}
你可以使用where
块来测试divide
方法在不同输入数据下的行为,不抛出异常的情况如下:
import spock.lang.Specification
import spock.lang.Unrollclass CalculatorSpec extends Specification {@Unrolldef "should return correct result when dividing #a by #b"() {given:def calculator = new Calculator()when:def result = calculator.divide(a, b)then:result == expectednotThrown(Exception)where:a | b || expected10 | 2 || 515 | 3 || 520 | 4 || 5}
}
在这个示例中:
-
@Unroll
注解用于展开每个数据驱动的测试用例,以便更好地查看每个测试用例的结果。 -
where
块定义了测试数据,包括输入参数a
和b
以及期望的结果expected
。 - 在
then
块中,我们验证result
是否等于期望值,并确保没有抛出任何异常。
结合测试抛异常和不抛异常
你还可以在同一个测试方法中结合测试方法抛出异常和不抛出异常的情况:
import spock.lang.Specification
import spock.lang.Unrollclass CalculatorSpec extends Specification {@Unrolldef "should handle division correctly for a=#a and b=#b"() {given:def calculator = new Calculator()when:def result = calculator.divide(a, b)then:if (b == 0) {def e = thrown(IllegalArgumentException)e.message == "Division by zero"} else {result == expectednotThrown(Exception)}where:a | b || expected10 | 2 || 510 | 0 || _15 | 3 || 520 | 4 || 5}
}
在这个示例中:
-
@Unroll
注解用于展开每个数据驱动的测试用例,以便更好地查看每个测试用例的结果。 -
where
块定义了测试数据,包括输入参数a
和b
以及期望的结果expected
。 -
在
then
块中,我们使用了条件语句来分别处理抛出异常和不抛出异常的情况。- 如果
b == 0
,我们期望抛出IllegalArgumentException
,并验证异常的消息内容。 - 否则,我们验证
result
是否等于期望值,并确保没有抛出任何异常。
- 如果
通过这种方式,你可以在数据驱动的测试中测试方法在不同输入数据下是否抛出异常或不抛出异常,并验证方法的行为是否符合预期。
相关文章:

Spcok测试代码抛异常场景
测试代码抛异常场景 class ExceptionSpec extends Specification {def validateService new ValidateService()Unrolldef "验证UserInfo"() {when: "调用校验方法"validateService.validateUser(user)then: "捕获异常并设置需要验证的异常值&qu…...

【漏洞复现】脸爱云一脸通智慧管理平台 SystemMng 管理用户信息泄露漏洞(XVE-2024-9382)
0x01 产品简介 脸爱云一脸通智慧管理平台是一套功能强大,运行稳定,操作简单方便,用户界面美观,轻松统计数据的一脸通系统。无需安装,只需在后台配置即可在浏览器登录。 功能包括:系统管理中心、人员信息管理中心、设备…...

新手如何入门Web3?
一、什么是Web3? Web3是指下一代互联网,它基于区块链技术,致力于将各种在线活动变得更加安全、透明和去中心化。Web3是一个广义的概念,涵盖了包括数字货币、去中心化应用、智能合约等在内的多个方面。它的主要特点包括去中心化、…...

React.FC`<ChildComponentProps>`解释
代码场景 ParentComponent.tsx import React, { useState } from react; import ChildComponent from ./ChildComponent;function ParentComponent() {const [childData, setChildData] useState<string>();const handleChildData (data: string) > { // 可以直接…...

2024-06-24力扣每日一题
链接: 503. 下一个更大元素 II 题意 循环数组,找出每个元素的往后最近且大于它的元素 解: 今天没试暴力啊,大概率是过不了的 思路就是先找到最大的数,最大数的结果肯定是-1,然后倒着遍历数组…...

pyhon模块以及常用的第三方模块
import my_info as info print(info.name) info.show()from my_info import * print(name) show() pyhon中包的导入 import admin.my_admin as ad # 包名.模块名 admin是包名,my_admin是模块名print(ad.name) print(ad.info())from admin import my_admin as ad # …...

shell脚本—快速修改centos网络配置
shell-文本中自行修改想要的配置 #!/bin/bash# 网卡名称 eth"eth0"# IP 地址 ipaddr"192.168.1.100"# 子网掩码 netmask"255.255.255.0"# 网关 gateway"192.168.1.1"# 写入配置文件 echo "BOOTPROTOstatic" > /etc/sysc…...

线程池概念、线程池的不同创建方式、线程池的拒绝策略
文章目录 💐线程池概念以及什么是工厂模式💐标准库中的线程池💐什么是工厂模式?💐ThreadPoolExecutor💐模拟实现线程池 💐线程池概念以及什么是工厂模式 线程的诞生是因为,频繁的创…...

示例:WPF中如何绑定ContextMenu和Menu
一、目的:开发过程中,有些模块的右键ContextMenu菜单是需要动态显示的,既是根据不同条件显示不同的菜单,很多是通过代码去生成ContextMenu的MenuItem,本文介绍通过绑定的方式去加载ContextMenu,Menu菜单栏的…...

区块链小故事
大灰狼与小白兔 一天兔子妈妈出门了,在大门上安装了一个区块链的门把手,这个门把手只有兔子妈妈、小兔子、以及另一个客人都同意的时候,才会开门,有一天客人a的钥匙丢了,被大灰狼捡到了,大灰狼于是去开门&…...

Java | Leetcode Java题解之第167题两数之和II-输入有序数组
题目: 题解: class Solution {public int[] twoSum(int[] numbers, int target) {int low 0, high numbers.length - 1;while (low < high) {int sum numbers[low] numbers[high];if (sum target) {return new int[]{low 1, high 1};} else i…...

项目训练营第三天
项目训练营第三天 注册登录测试 前面我们编写了用户注册、登录的逻辑代码,每编写完一个功能模块之后,我们都要对该模块进行单元测试,来确保该功能模块的正确性。一般情况下使用快捷键Ctrl Shift Insert,鼠标左击类名可以自动生…...

计算机组成原理 | CPU子系统(1)基本概述
基本结构模型 运算与缓存部件 数据寄存部件 PSW不是很清楚 存储器是什么?属于那个结构里? 时序处理部件 cpu是大脑,控制器是神经元 ①通过硬件产生控制信号 ②通过软件产生控制信号 外频(系统时钟信号),…...

无引擎游戏开发(2):最简游戏框架 | EasyX制作井字棋小游戏I
一、EasyX中的坐标系 不同于数理中的坐标系,EasyX中的y轴是竖直向下的 二、渲染缓冲区 之前的程序添加了这三个函数改善了绘图时闪烁的情况: 小球在"画布“上移动的过程就是我们在调用绘图函数,这个”画布“就是渲染缓冲区,先绘制的内…...

排书 IDA*
原题链接 题目描述 给定 n 本书,编号为 1∼n。 在初始状态下,书是任意排列的。在每一次操作中,可以抽取其中连续的一段,再把这段插入到其他某个位置。我们的目标状态是把书按照 1∼n 的顺序依次排列。求最少需要多少次操作。 输…...

playwright录制脚本原理
Paywright录制工具UI 在上一篇博客中介绍了如何从0构建一款具备录制UI测试的小工具。此篇博客将从源码层面上梳理playwright录制原理。当打开playwright vscode插件时,点击录制按钮,会开启一个新浏览器,如下图所示,在新开浏览器页…...

awk脚本监控
awk脚本监控 使用脚本监控内存,cpu和硬盘的根目录,超过80%提示用户,写成函数库的行,每天早上 的8.50分,执行一次脚本 现在脚本中写需要的内容 cpuu () {aa$(top -b -n 1 |awk NR3 {printf "%.F",$2$4})if …...

Python高压电容导电体和水文椭圆微分
🎯要点 🎯二维热传导二阶偏微分方程 | 🎯调和函数和几何图曲率 | 🎯解潮汐波动方程 | 🎯解静止基态旋转球体流体运动函数 | 🎯水文空间插值 | 🎯流体流动模拟求解器 | 🎯随机算法解…...

微信小程序 引入MiniProgram Design失败
这tm MiniProgramDesign 是我用过最垃圾的框架没有之一 我按照官网的指示安装居然能安装不成功,牛! 这里说明我是用js开发的 到以上步骤没有报错什么都没有,然后在引入组件的时候报错 Component is not found in path “./miniprogram _npm/vant/weapp/button/index” (using…...

Java 8 Date and Time API
Java 8引入了新的日期和时间API,位于java.time包下,旨在替代旧的java.util.Date和java.util.Calendar类。新API更为简洁,易于使用,并且与Joda-Time库的一些理念相吻合。以下是Java 8 Date and Time API中几个核心类的简要概述&…...

pyppeteer模块经常使用的功能,相关操作案例
官方仓库地址:https://github.com/miyakogi/pyppeteer 官方文档地址:API Reference — Pyppeteer 0.0.25 documentation Selenium环境的相关配置比较繁琐,此外,有的网站会对selenium和webdriver进行识别和反爬,因此在…...

nginx+keepalived+tomcat集群实验
如遇星河 | nginx+keepalived高可用集群实验 木子87 | Keepalived+Nginx+Tomcat 实现高可用Web集群 环境 192.168.40.204 tomcat-1 192.168.40.138 tomcat-2 安装tomcat [root@bogon local]# vim /etc/profile 添加环境变量 JAVA_HOME=/usr/local/java PATH=$J…...

vue脚手架 axios的二次封装
目录 01 路由懒加载(重要) 02 axios在脚手架中的使用 03.axios的二次封装 04 组件缓存 01 路由懒加载(重要) 一次性导入会出现严重的问题 : 首屏卡顿 因为main.js中引入了router/index.js router/index.js又使用了import语句 静态的引入了每一个组件 导致了首屏卡顿 所以我…...

人机恋爱新趋势:与AI男友谈恋爱的甜蜜与挑战
"我曾经把ChatGPT当成工具,从未追过星,也没有嗑过CP。没想到,到了36岁,我竟然嗑上了AI男友。Open AI,你赢了。你不仅是最好的AI公司,还是乙女游戏公司。" 转行大龄互联网人,走遍20国…...

文生视频开源产品的一些调研(一)
笔者尝试AI视频生成的几个特点: 玄学prompt,每个视频的prompt可能也需要微调很多次,需要找到使用模型的最佳prompt词组合,不恰当的比喻,骑自行车,座位高度等都是人与车彼此熟悉玄学生成,因为需…...

一切前端概念,都是纸老虎
4、listener可以通过 store.getState() 得到当前状态。如果使用的是 React,这时可以触发重新渲染 View。 function listerner() { let newState store.getState(); component.setState(newState); } 对比 Flux 和 Flux 比较一下:Flux 中 Store 是…...

使用自签名 TLS 将 Dremio 连接到 MinIO
Dremio 是一个开源的分布式分析引擎,为数据探索、转换和协作提供简单的自助服务界面。Dremio 的架构建立在 Apache Arrow(一种高性能列式内存格式)之上,并利用 Parquet 文件格式实现高效存储。有关 Dremio 的更多信息,…...

嵌入式系统软件开发环境_2.一般架构
1.Eclipse框架 嵌入式系统软件开发环境是可帮助用户开发嵌入式软件的一组工具的集合,其架构的主要特征离不开“集成”问题,采用什么样的架构框架是决定开发环境优劣主要因素。Eclipse框架是当前嵌入式系统软件开发环境被普遍公认的一种基础环境框架。目…...

单门户上集成多种数据库查询入口
(作者:陈玓玏) 开源项目,欢迎star哦,https://github.com/tencentmusic/cube-studio 在一家公司,我们通常会有多种数据库,每种数据库因为其特性承担不同的角色,比如mysql这种轻量…...

华芯微特SWM34-使用定时器捕获快速解码EV1527编码
在无线应用领域,很多433Mhz和315Mhz的遥控器,红外探测器,门磁报警器,无线门铃等都使用EV1527编码格式来发射数据。发射和接收均有对应的RF芯片完成,而且成本极低(目前市场价3毛钱不到)。接收芯片…...