欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JUnit5相关内容简介

程序员文章站 2023-12-18 10:00:22
著名的java单元测试框架junit 4已经出来很长时间了,当时我发现junit 5已经处于测试版,就准备写文章来介绍junit 5.不过因为还是测试版,所以有些地方还不太...

著名的java单元测试框架junit 4已经出来很长时间了,当时我发现junit 5已经处于测试版,就准备写文章来介绍junit 5.不过因为还是测试版,所以有些地方还不太完善,我也有点懒没有好好写。这几天突然想起这事了,在到官网上查看,发现就在9月10日,junit 5的正式版终于出来了!那么我就正好把文章重新好好写写,为大家介绍这个最新的junit框架。

框架结构

和junit 4相比,junit 5的结构非常清晰,为自定义插件、ide测试执行等扩展功能做了很好的支持。这一点从项目结构就可以看出来。

junit platform

这一组的包名是org.junit.platform,从名字就可以看到,这一组的主要功能就是作为测试框架的基础平台。这个包下的模块包含基础api、执行引擎及执行器、基本的命令行执行功能、命令行界面、maven及gradle的测试插件等最基本的功能。

junit jupiter

jupiter 是junit 5的代号,这个包下的模块包含junit 5的主要功能。如果我们要使用junit 5,那么必然要包含这一组模块。

junit vintage

vintage 是旧版本junit 的代号,这个包下的模块可以让我们在新的junit平台上运行旧的junit 3 和 4 的测试。

导入类库

在junit 5还在测试阶段的时候,官方文档上还有在maven和gradle中集成junit 5的例子。但是到了正式版,这一部分的内容消失了,仅仅留下两个示例项目的链接,让我们自己参考(复制粘贴)。

使用maven

是官方的maven例子。本来我准备把相关的pom配置贴到这里,但是一看maven的配置太长了,所以还是算了。如果有需求的话请自己查看这个项目的pom配置。

使用gradle

如果用gradle的话,那么这个问题就简单多了。在junit5-gradle-consumer 示例项目中也有比较详细的说明。

首先,gradle默认不支持junit 5,,所以需要启用junit platform gradle 插件来支持。

buildscript {
 repositories {
 mavencentral()
 }
 dependencies {
 classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0'
 }
}
apply plugin: 'org.junit.platform.gradle.plugin'

然后是关于这个gradle插件的配置。默认情况下所有的引擎和标签都会被执行。如果你想选择只执行某些引擎和标签的测试,可以取消下面的注释并按照你自己的需求进行修改。当然假如你没有这些高级需求,可以把这一部分删掉。

junitplatform {
 // platformversion '1.0.0'
 filters {
 engines {
  // include 'junit-jupiter', 'junit-vintage'
  // exclude 'custom-engine'
 }
 tags {
  // include 'fast'
  exclude 'slow'
 }
 // includeclassnamepattern '.*test'
 }
 // enablestandardtesttask true
 // reportsdir file('build/test-results/junit-platform') // this is the default
 // logmanager 'org.apache.logging.log4j.jul.logmanager'
}

如果你只需要运行junit 5测试,只需要导入下面两个依赖项。junit platform的依赖会自动导入。

dependencies {
 testcompile("org.junit.jupiter:junit-jupiter-api:5.0.0")
 testruntime("org.junit.jupiter:junit-jupiter-engine:5.0.0")
}

如果你想在新平台下运行旧的junit 3和4测试,需要导入下面的依赖项。

dependencies {
 testcompile("junit:junit:4.12")
 testruntime("org.junit.vintage:junit-vintage-engine:4.12.0")
}

编写测试

junit 4测试

如果前面都配置好了,现在就可以开始编写测试了。首先先来复习一下旧的junit 4测试。

public class junit4test {
	@beforeclass
	 public static void init() {
		system.out.println("before class");
	}
	@afterclass
	 public static void clean() {
		system.out.println("after class");
	}
	@before
	 public void before() {
		system.out.println("before");
	}
	@after
	 public void after() {
		system.out.println("after");
	}
	@test
	 public void test1() {
		system.out.println("test 1");
	}
	@test
	 public void test2() {
		system.out.println("test 2");
	}
}

使用gradle test等命令执行一下,就会执行这个测试。结果类似于这样。

before class
before
test 1
test 2
after
after class

junit 5测试

让我们来看看等效的junit 5测试怎么写。可以看到最明显的变化:首先几个注解被重新命名成更见名知义的名称;另外一点是测试方法不必是公有方法,这样我们可以少敲几下键盘。

public class junit5test {
	@beforeall
	 static void beforeall() {
		system.out.println("before all");
	}
	@afterall
	 static void afterall() {
		system.out.println("after all");
	}
	@beforeeach
	 void before() {
		system.out.println("before");
	}
	@aftereach
	 void after() {
		system.out.println("after");
	}
	@test
	 void test1() {
		system.out.println("test 1");
	}
	@test
	 void test2() {
		system.out.println("test 2");
	}
}

编写断言

为了验证测试用例是否正确,我们需要编写一些断言。junit 5自带了很多断言,可以帮助我们编写测试用例。而且这些断言都带有可以接受lambda表达式的重载版本,非常适合java 8使用。当然我个人认为断言还是assertj更方便一点。

import static org.junit.assert.asserttrue;
import static org.junit.jupiter.api.assertions.*;

public class assertiondemo {
 @test
 void testassertion() {
 assertequals(10, 10);
 asserttrue(true);
 assertequals(100, 100, "两个数相等");
 assertall("数字"
  , () -> assertequals("name", "name")
  , () -> assertequals(500, 500));
 assertthrows(invalidparameterexception.class
  , () -> {
   throw new invalidparameterexception();
  }
 );
 int result = asserttimeout(duration.ofseconds(5)
  , () -> {
   int i = 0, j = 0;
   while (i <= 100) {
   for (; j <= 100000; j++)
    j++;
   i++;
   }
   return i;
  });
 assertequals(100, result);
 }
}

依赖注入

现在测试类的构造方法和测试方法都可以接受参数了。parameterresolver接口定义了如何在运行时注入参数的方法。内置的几个可以让我们获取测试用例运行时的信息。

首先是testinfoparameterresolver。如果方法上有testinfo类型的实例,junit 5框架就会自动注入该实例,这个实例的几个方法可以让我们获取测试类和测试方法的名称、显示名称、标签等信息。

public class dependencyinjectiondemo {
 @test
 @displayname("依赖注入")
 @tag("test")
 void testdisplayname(testinfo testinfo) {
 assertequals("依赖注入", testinfo.getdisplayname());
 assertequals(collections.singleton("test"), testinfo.gettags());
 }
}

还有repetitioninfoparameterresolver等内置参数解析器,将在后面介绍。

常用注解

显示名称

我们可以为测试类和测试方法添加自定义的名称,这些名贵会由测试运行器和测试报告所显示。显示名称没有变量名那样的显示,可以是一段包含空格的长字符串,甚至还可以是emoji表情。

@displayname("测试类可以指定显示名称")
public class displaynamedemo {
	@test
	 @displayname("测试方法也可以指定显示名称")
	 void testwithlongdisplayname() {
	}
	@test
	 @displayname("显示名称还可以包含表情��")
	 void testwithdisplaynamewithemoji() {
	}
}

禁用测试

@disabled注解可以用到测试类或测试方法上,可以禁用对应的测试。

@disabled
public class disabledtestdemo {
 @test
 //@disabled
 void testdisabled() {

 }
}

重复测试

如果需要让某个测试方法运行多次,使用@repeatedtest注解。

public class repeatedtestdemo {
 @repeatedtest(10)
 void testrepeated10times() {

 }
}

还可以注入一个实例repetitioninfo,检查当前重复次数和总的重复次数。

public class repeatedtestdemo {
	@beforeeach
	 void beforeeach(repetitioninfo info) {
		system.out.printf("%d - %d\n"
		    , info.getcurrentrepetition()
		    , info.gettotalrepetitions());
	}
	@repeatedtest(10)
	 void testrepeated10times() {
	}
}

附带标签

在前面介绍配置gradle的时候就说了,在配置中可以选择过滤某些标签的测试。要在代码中给标签也很简单,直接用@tag注解即可。

@tag("taggedtest")
public class tagdemo {
	@test
	 @tag("taggedtest1")
	 void testwithtag1() {
	}
	@test
	 @tag("taggedtest2")
	 void testwithtag2() {
	}
}

嵌套测试

有时候可能需要嵌套测试来表明某些测试之间的包含关系。嵌套测试使用@nested注解。

@displayname("外层测试")
public class nesteddemo {
 @test
 void testouter() {
 }

 @nested
 @displayname("内层测试")
 class innertestdemo {
  @test
  void testinner() {
  }
 }
}

需要注意只有费静态内部类才能使用nested注解。另外,由于java不允许内部类有静态方法,所以也不能有@beforeall和@afterall注解。如果想要突破这个限制,需要在嵌套内部类上添加@testinstance(lifecycle.per_class)注解,详情参见test instance lifecycle

ide支持

虽然现在junit 5已经出来了。但是各种工具链的支持还没有跟上。目前只有intellij idea和eclipse 4.7 (oxygen)添加了对junit 5的支持。所以如果在正式场合的话,使用junit 4还是更稳妥一点。

常见问题

区分不同版本间的@test注解

就在我写这篇文章的时候, 我的测试小例子就遇到了一个问题,测试通不过,显示如下的错误信息。

failures (1):
 junit vintage:yitian.study.test.assertiondemo:initializationerror
 classsource [classname = 'yitian.study.test.assertiondemo', fileposition = null]
 => java.lang.exception: method testassertion() should be public

英文好的同学应该可以认出来,这个错误信息说的是测试方法必须是公开的。但是前面明明说了,junit 5取消了这个限制,那么为什么还会出现这个错误呢?我仔细一看,发现了错误所在。可能是由于以前junit 4用的比较多,所以ide默认对于@test这个注解,自动补全的是这个。

import org.junit.test;

这个包是junit 4下的@test注解。如果我们要使用junit 5的话,需要的是以下这个@test注解。

import org.junit.jupiter.api.test;

修改之后,再次运行测试,果然没有问题了。当然这里为了学习和使用,我同时引用了junit 4的包,所以才会出现这个冲突。如果没有什么特殊需求的话,建议只导入junit 5的jar包,防止出现混淆。当然都导入也可以,只不过你就需要小心区分,不要把junit 4的注解写到junit 5的测试上。最后附上我的,有兴趣的同学可以看看。

总结

以上就是本文关于junit5相关内容简介的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

上一篇:

下一篇: