document.addeventlistener方法不执行_JUnit 5 测试方法的执行优先级
前言
使用單元測試有時對方法的執(zhí)行順序有要求,而默認情況下測試方法的執(zhí)行并非按照編寫順序,這就導(dǎo)致測試用例因執(zhí)行順序而導(dǎo)致的不通過。這里我使用的JUnit版本是5.6.2,下面講述如何自定義測試方法的執(zhí)行優(yōu)先級。
@TestMethodOrder
這個注解標(biāo)注在測試類上,用于指定測試方法要以怎樣的方式確定執(zhí)行順序:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface TestMethodOrder {Class<? extends MethodOrderer> value(); }value()接收一個MethodOrderer類型,這個類型是一個接口,里面重要的有一個接口方法orderMethods以及三個靜態(tài)實現(xiàn)類,分別是:Random、OrderAnnotation、Alphanumeric:
public interface MethodOrderer {void orderMethods(MethodOrdererContext context);default Optional<ExecutionMode> getDefaultExecutionMode() {return Optional.of(ExecutionMode.SAME_THREAD);}// 隨機順序class Random implements MethodOrderer {// ...}// 根據(jù)@Order注解確定執(zhí)行順序,注意這個注解在org.junit.jupiter.api包下class OrderAnnotation implements MethodOrderer {// ...}// 按照方法名字母升序順序,如果方法名相同,則拿方法的參數(shù)列表類型名稱比較class Alphanumeric implements MethodOrderer {// ...} }其中比較重要的是void orderMethods(MethodOrdererContext context);接口方法,如果你不滿足于默認提供的三種實現(xiàn),可以實現(xiàn)此方法,方法參數(shù)MethodOrdererContext可以獲得測試方法的上下文信息,據(jù)此定制方法執(zhí)行順序。一般來說上述提供的三種實現(xiàn)已基本滿足需求,有需要可參照三種實現(xiàn)。
Random
隨機確定方法執(zhí)行順序,只需要在測試類上標(biāo)注如下:
@TestMethodOrder(MethodOrderer.Random.class) class SampleTests {// methods ... }以下是Random的關(guān)鍵源碼:
class Random implements MethodOrderer {private static final long DEFAULT_SEED;static {DEFAULT_SEED = System.nanoTime(); // 默認的隨機種子是系統(tǒng)時間,單位納秒}public static final String RANDOM_SEED_PROPERTY_NAME = "junit.jupiter.execution.order.random.seed"; // 在配置文件中指定隨機種子,這個值必須是數(shù)值型@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
如果需要為特定的方法指定執(zhí)行順序,需要在測試類上標(biāo)注@TestMethodOrder(MethodOrderer.OrderAnnotation.class) ,這個注解不能夠單獨使用,需要配合方法上的注解org.junit.jupiter.api.Order確定執(zhí)行順序,你可以只為希望按順序執(zhí)行的方法標(biāo)注此注解,而不是所有方法:
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) class SampleTests {@Test@Order(1) // 優(yōu)先執(zhí)行void shouldUploadFileSuccess() throws Exception {}@Test@Order(2) // 延后執(zhí)行void shouldDeleteFileSuccess() throws Exception {}@Test // 不會因執(zhí)行順序而導(dǎo)致失敗,可不指定@Ordervoid shouldListAllFiles() throws Exception {} }@Order注解中的value越小越優(yōu)先執(zhí)行,沒有標(biāo)注@Order的方法使用的是DEFAULT值:
@Target({ ElementType.FIELD, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Order {int DEFAULT = Integer.MAX_VALUE / 2;int value(); }下面是OrderAnnotation實現(xiàn):
class OrderAnnotation implements MethodOrderer {@Overridepublic void orderMethods(MethodOrdererContext context) {// java.util.Comparator.comparingIntcontext.getMethodDescriptors().sort(comparingInt(OrderAnnotation::getOrder));}// 獲取方法上@Order注解的value,沒有標(biāo)注@Order注解的方法使用的是@Order注解上的DEFAULT值private static int getOrder(MethodDescriptor descriptor) {return descriptor.findAnnotation(Order.class).map(Order::value).orElse(Order.DEFAULT);}}方法排序表面使用的是Comparator接口的靜態(tài)方法comparingInt,實際使用的是java.lang.Integer.compare的比較邏輯:
public static int compare(int x, int y) {return (x < y) ? -1 : ((x == y) ? 0 : 1);}Alphanumeric
按照方法名的字母升序排序執(zhí)行,如果方法名相同,則拿方法的參數(shù)列表類型名稱比較:
@TestMethodOrder(MethodOrderer.Alphanumeric.class) class AlphaTests {@Test // 后執(zhí)行void b() {}@Test // 先執(zhí)行void a() {} }下面是這種方式的實現(xiàn):
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())// 如果測試方法的名稱相同,則進一步比較方法上的參數(shù)列表的類型.thenComparing(descriptor -> parameterList(descriptor.getMethod()));// 將方法的參數(shù)列表類型處理成形如:java.lang.String,java.lang.Integerdprivate static String parameterList(Method method) {return ClassUtils.nullSafeToString(method.getParameterTypes());}}上面parameterList方法用到的ClassUtils是JUnit自身的,實際并沒什么可看,就是對給定的類型列表名稱做逗號拼接處理(使用的是Java 8中的函數(shù)式編程,自行了解):
public final class ClassUtils {private ClassUtils() {}public static String nullSafeToString(Class<?> clazz) {return clazz == null ? "null" : clazz.getName();}// method.getParameterTypes()得到的是一個數(shù)組,所以使用的的是這個方法public static String nullSafeToString(Class<?>... classes) {// Class:getName => clazz -> clazz.getNamereturn nullSafeToString(Class::getName, classes);}// Function<? super Class<?>, ? extends String> mapper表示傳入的是一個Class類型,// 將會產(chǎn)生一個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)將調(diào)用nullSafeToString(Class::getName, classes)// 中的Class::getName用于獲取類型限定名稱return clazz == null ? "null" : (String)mapper.apply(clazz);}).collect(Collectors.joining(", ")) : "";} }軟件版本
| JUnit | 5.6.2(junit-jupiter) |
總結(jié)
以上是生活随笔為你收集整理的document.addeventlistener方法不执行_JUnit 5 测试方法的执行优先级的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: node --- [跨域] 预检请求
- 下一篇: 服务器网盘系统怎么装,云服务器上怎么安装