document.addeventlistener方法不执行_JUnit 5 测试方法的执行优先级

67301366e11ad47ad3d19c0455cac9c0.png

前言

使用单元测试有时对方法的执行顺序有要求,而默认情况下测试方法的执行并非按照编写顺序,这就导致测试用例因执行顺序而导致的不通过。这里我使用的JUnit版本是5.6.2,下面讲述如何自定义测试方法的执行优先级。

@TestMethodOrder

这个注解标注在测试类上,用于指定测试方法要以怎样的方式确定执行顺序:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface TestMethodOrder {Class<? extends MethodOrderer> value();
}

value()接收一个MethodOrderer类型,这个类型是一个接口,里面重要的有一个接口方法orderMethods以及三个静态实现类,分别是:RandomOrderAnnotationAlphanumeric

public interface MethodOrderer {void orderMethods(MethodOrdererContext context);default Optional<ExecutionMode> getDefaultExecutionMode() {return Optional.of(ExecutionMode.SAME_THREAD);}// 随机顺序class Random implements MethodOrderer {// ...}// 根据@Order注解确定执行顺序,注意这个注解在org.junit.jupiter.api包下class OrderAnnotation implements MethodOrderer {// ...}// 按照方法名字母升序顺序,如果方法名相同,则拿方法的参数列表类型名称比较class Alphanumeric implements MethodOrderer {// ...}
}

其中比较重要的是void orderMethods(MethodOrdererContext context);接口方法,如果你不满足于默认提供的三种实现,可以实现此方法,方法参数MethodOrdererContext可以获得测试方法的上下文信息,据此定制方法执行顺序。一般来说上述提供的三种实现已基本满足需求,有需要可参照三种实现。

Random

随机确定方法执行顺序,只需要在测试类上标注如下:

@TestMethodOrder(MethodOrderer.Random.class)
class SampleTests {// methods ...
}

以下是Random的关键源码:

class Random implements MethodOrderer {private static final long DEFAULT_SEED;static {DEFAULT_SEED = System.nanoTime(); // 默认的随机种子是系统时间,单位纳秒}public static final String RANDOM_SEED_PROPERTY_NAME = "junit.jupiter.execution.order.random.seed"; // 在配置文件中指定随机种子,这个值必须是数值型@Overridepublic void orderMethods(MethodOrdererContext context) {// 对方法随机洗牌Collections.shuffle(context.getMethodDescriptors(),new java.util.Random(getCustomSeed(context).orElse(DEFAULT_SEED)));}// 获取配置文件中指定的随机种子private Optional<Long> getCustomSeed(MethodOrdererContext context) {return context.getConfigurationParameter(RANDOM_SEED_PROPERTY_NAME).map(configurationParameter -> {Long seed = null;try {seed = Long.valueOf(configurationParameter);}catch (NumberFormatException ex) {}return seed;});}}

OrderAnnotation

如果需要为特定的方法指定执行顺序,需要在测试类上标注@TestMethodOrder(MethodOrderer.OrderAnnotation.class) ,这个注解不能够单独使用,需要配合方法上的注解org.junit.jupiter.api.Order确定执行顺序,你可以只为希望按顺序执行的方法标注此注解,而不是所有方法:

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class SampleTests {@Test@Order(1) // 优先执行void shouldUploadFileSuccess() throws Exception {}@Test@Order(2) // 延后执行void shouldDeleteFileSuccess() throws Exception {}@Test // 不会因执行顺序而导致失败,可不指定@Ordervoid shouldListAllFiles() throws Exception {}
}

@Order注解中的value越小越优先执行,没有标注@Order的方法使用的是DEFAULT值:

@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Order {int DEFAULT = Integer.MAX_VALUE / 2;int value();
}

下面是OrderAnnotation实现:

class OrderAnnotation implements MethodOrderer {@Overridepublic void orderMethods(MethodOrdererContext context) {// java.util.Comparator.comparingIntcontext.getMethodDescriptors().sort(comparingInt(OrderAnnotation::getOrder));}// 获取方法上@Order注解的value,没有标注@Order注解的方法使用的是@Order注解上的DEFAULT值private static int getOrder(MethodDescriptor descriptor) {return descriptor.findAnnotation(Order.class).map(Order::value).orElse(Order.DEFAULT);}}

方法排序表面使用的是Comparator接口的静态方法comparingInt,实际使用的是java.lang.Integer.compare的比较逻辑:

public static int compare(int x, int y) {return (x < y) ? -1 : ((x == y) ? 0 : 1);}

Alphanumeric

按照方法名的字母升序排序执行,如果方法名相同,则拿方法的参数列表类型名称比较:

@TestMethodOrder(MethodOrderer.Alphanumeric.class)
class AlphaTests {@Test // 后执行void b() {}@Test // 先执行void a() {}
}

下面是这种方式的实现:

class Alphanumeric implements MethodOrderer {@Overridepublic void orderMethods(MethodOrdererContext context) {context.getMethodDescriptors().sort(comparator);}private static final Comparator<MethodDescriptor> comparator = Comparator.<MethodDescriptor, String>// 拿方法名比较 comparing(descriptor -> descriptor.getMethod().getName())// 如果测试方法的名称相同,则进一步比较方法上的参数列表的类型.thenComparing(descriptor -> parameterList(descriptor.getMethod()));// 将方法的参数列表类型处理成形如:java.lang.String,java.lang.Integerdprivate static String parameterList(Method method) {return ClassUtils.nullSafeToString(method.getParameterTypes());}}

上面parameterList方法用到的ClassUtilsJUnit自身的,实际并没什么可看,就是对给定的类型列表名称做逗号拼接处理(使用的是Java 8中的函数式编程,自行了解):

public final class ClassUtils {private ClassUtils() {}public static String nullSafeToString(Class<?> clazz) {return clazz == null ? "null" : clazz.getName();}// method.getParameterTypes()得到的是一个数组,所以使用的的是这个方法public static String nullSafeToString(Class<?>... classes) {// Class:getName => clazz -> clazz.getNamereturn nullSafeToString(Class::getName, classes);}// Function<? super Class<?>, ? extends String> mapper表示传入的是一个Class类型,// 将会产生一个String类型public static String nullSafeToString(Function<? super Class<?>, ? extends String> mapper, Class<?>... classes) {Preconditions.notNull(mapper, "Mapping function must not be null");return classes != null && classes.length != 0 ? (String)Arrays.stream(classes).map((clazz) -> {// mapper.apply(clazz)将调用nullSafeToString(Class::getName, classes)// 中的Class::getName用于获取类型限定名称return clazz == null ? "null" : (String)mapper.apply(clazz);}).collect(Collectors.joining(", ")) : "";}
}

软件版本

软件版本
JUnit5.6.2(junit-jupiter)

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

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

相关文章

2异常处理_Java处理异常2种机制关键字区别解析

在异常处理的过程中,throws和throw的区别是?throws:是在方法上对一个方法进行声明,而不进行处理,而是向上传,谁调用谁处理.throw:是在具体的抛出一个异常类型.throws的栗子:throws的话,就是这个方法有可能会产生异常,而我只是将它声明出去,我自己不处理,如果有人调用的时候,可…

TL431的用法

TL431是可控精密稳压源。它的输出电压用两个电阻就可以设置从Vref&#xff08;2.5V&#xff09;到36V范围内的任何值。该器件的典型动态阻抗为0.2Ω&#xff0c;在很多应用中用它代替稳压二极管&#xff0c;例如&#xff0c;数字电压表&#xff0c;运放电路&#xff0c;可调压电…

AD16原理图.schdot中批量修改标签中的文本字体、大小、颜色

1&#xff09;使用鼠标左键区域选中需要修改的文本&#xff0c;或按住shift键使用鼠标左键选择分布在图中各处的需要修改的文本 2&#xff09;按住shift键&#xff0c;鼠标左键双击选中的任一文本&#xff0c;弹出如下的SCH Inspector弹窗 3&#xff09;在SCH Inspector弹窗中…

12v小型电机型号大全_鄂破碎机型号大全图,小型鄂破碎机价格

鄂破碎机&#xff0c;粗碎加工主力配置&#xff0c;因为使用频繁&#xff0c;很多案例都少不了&#xff0c;所以设备生产厂家有很多&#xff0c;但是随时鄂破碎机的机型更新&#xff0c;核心性能越来越完善&#xff0c;整机时产更高&#xff0c;而且环保性能更强悍。鄂破碎机型…

我的第一次Pascal程序

今天刚刚来学点Pascal语言&#xff0c;都怪我买的书大多是用Pascal语言写的&#xff0c;所以我只能试着学一点咯&#xff01; 来一段程序员最经典的Hello World&#xff01; 1 program exl_2; 2 begin 3 write(Hello World!); 4 end. 转载于:https://www.cnblogs.com/ECJTU…

C#中的前台线程和后台线程的区别

前台线程&#xff1a;应用程序必须运行完所有的前台线程才能退出&#xff0c;默认创建的线程都是前台线程。 后台线程&#xff1a;应用程序可以不必考虑后台线程是否已经运行完毕&#xff08;包括正常退出和异常退出&#xff09;&#xff0c;只要所有的前台线程结束&#xff0…

C#中string.Concat方法的使用

string.Concat方法用于连接string的一个或多个实例&#xff0c;或string的一个或多个实例的object表示形式 https://docs.microsoft.com/zh-cn/dotnet/api/system.string.concat?viewnet-5.0 1&#xff09;连接string[]或object[]数组中的元素 using System; using System.C…

将java项目做成app_将鸿蒙做成和EMUI一致,又兼容安卓APP,华为已立于不败之地...

自从华为的系统曝光以来&#xff0c;每天都有众多的网友为其摇旗呐喊&#xff0c;说不管怎么时候推出&#xff0c;甚至就算不好用&#xff0c;都无条件支持&#xff0c;说如果连自己人都不支持&#xff0c;就不可能成功了。但近日&#xff0c;随着网上曝光华为鸿蒙系统的的相关…

C# 使用StackFrame和StackTrace类 获取当前函数名,当前代码行,源代码文件

https://docs.microsoft.com/zh-cn/dotnet/api/system.diagnostics.stackframe?viewnetframework-3.0 https://docs.microsoft.com/zh-cn/dotnet/api/system.diagnostics.stacktrace?viewnetframework-3.0 测试代码如下&#xff1a; using System; using System.Collections…

2017-03-16 Codeforces 453A 概率期望,思维 UOJ 228(待补)

Codeforces 453A A. Little Pony and Expected Maximum 题意&#xff1a;一个m面质地均匀的骰子&#xff0c;每面出现的概率都是独立的1/m, 你需要投掷n次&#xff0c;其结果是这n次出现的最大点数。问投掷n次骰子的结果的期望值是多少&#xff0c;要求相对误差或绝对误差不…

vuex的命名空间有哪些_Vue 3 带来的 Vuex 的替代方案

一、前言就像是 React 社区在 HOOK API 出现后很快就使用 useReducer、useContext 代替了 Redux 进行状态管理一样。Vue3 也是时候抛弃 Vuex 进行状态管理了。在考虑为什么要抛弃 Vuex 之前&#xff0c;我们先来想一下为什么要引入 Vuex&#xff1f;Vuex 实际上解决的问题是「组…

C# Task异步编程

1、不适用异步的示例 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; using System.Net; using System.Diagnostics;namespace ConsoleApplication1 {class MyDownloadStrin…

人形图案c语言程序_最多 280 字符,你能用 Basic 玩出哪些花样程序来?

(给程序员的那些事加星标)转自&#xff1a;机器之心【导读】&#xff1a;推特与计算机能擦出什么样的火花呢&#xff1f;大多数人可能就想到在计算机上发推特呗。但是&#xff0c;有人就不这么想。酷爱计算机演进史和推特的 Dominic Pajak 创建了 BBC Micro Bot&#xff0c;它能…

???--???二进制变换

题意 &#xff1a; 定义两种变换 1 &#xff1a; i i - 1 2 &#xff1a; i i - lowbit (i) 定义函数Calc(i,j)为二进制意义下 i 变换到 j 的最小步数。 给你一个二进制整数 n&#xff0c;要求 sigma {(i 1 -> n) sigma {(j 0 -> i - 1) Calc (i,j)}} 数据范围 : 令…

C# 派生类的构造函数

假定没有为任何类定义任何显式的构造函数,这样编译器就会为所有的类提供默认的初始化构 造函数,在后台会进行许多操作,但编译器可以很好地解决类的层次结构中的所有问题,每个类中 的每个字段都会初始化为对应的默认值。但在添加了一个我们自己的构造函数后,就要通过派生类 的层…

js 获取url问号前_PHP获取指定网页的HTML代码并执行输出

PHP获取指定网页的HTML代码并执行输出&#xff0c;这个方法主要是将所要或取目标的URL地址的网站中获取相关内容到自己的网页中。代码如下&#xff1a;<?php $srcurl "所要截取目标的URL地址"; $handle fopen($srcurl,"rb"); $content fread($handl…

AD16画线时如何切换90°、45°、任意角度画线模式

在绘图界面选择画线后&#xff0c;使用“shift空格”可切换不同的画线模式。切换过程中会有90模式、45度模式、任意角度模式等&#xff0c;在这些模式中可使用空格键在进行细分切换。 1、90模式 2、45模式 3、任意模式

1200兆路由器网速_如何选购路由器才能发挥宽带的网速?

很多人多少都会遇到家里宽带网速慢的时候&#xff0c;家中明明是光纤宽带&#xff0c;可是网速却没有想象中的那么快&#xff1f;尤其是宽带的带宽升级到100M、200M、500M的时候&#xff0c;感觉跟没有提速一样。也许你家的路由器该换新啦&#xff01;那么&#xff0c;想要选购…

C# 静态类

------《C#高级编程》第7版

vant实现下拉刷新和上拉加载_微信小程序 - 实现下拉刷新、上拉加载

在小程序开发中使用下拉刷新和上拉加载非常多&#xff0c;比如常用的展示型首页&#xff0c;而实现这个功能有两种形式&#xff0c;第一种是使用 scroll-view 组件&#xff0c;第二种是不使用 scroll-view 组件而让整个页面刷新&#xff0c;那就分别都在此简单分享下。方法一在…