点击跳转到系列博文目录导航
junit5中的JUnit Jupiter提供了Assertions类来替代了junit4中的Assert类并且添加了一些新的方法,所以工作过程中完全可以使用Assertions代替Assert类。
其包名称为:org.junit.jupiter.api.Assertions
Assertions中提供的方法都是静态方法,我们可以通过import静态资源进行使用,例如:
import static org.junit.jupiter.api.Assertions.*;
当然上述是导入了所有的方法,单独导入也可。
下面对Assertions进行一个简单的应用
代码的注释都很清楚,就不再多说了
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static java.time.Duration.ofMillis;
import static java.time.Duration.ofMinutes;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author liyangyang
* @date 2019/1/8
*/
class AssertionsDemo {
//定义一个person对象,Person类里面有两个参数lastName,firstName
static Person person = new Person();
/**
* 使用 @BeforeAll注解在所有测试方法执行前执行person对象的赋值
*/
@BeforeAll
static void initPerson(){
person.setFirstName("John");
person.setLastName("Doe");
}
/**
* assertEquals比较两个值是否相同
* assertTrue 判断括号里面的参数是否为true
*/
@Test
void standardAssertions() {
assertEquals(2, 2);
//当不相等时,会打印出第三个参数,下面的所有的此类型的参数都是这种作用
assertEquals(4, 5, "The optional assertion message is now the last parameter.");
assertTrue('a' < 'b', "Assertion messages can be lazily evaluated -- "
+ "to avoid constructing complex messages unnecessarily.");
}
/**
* assertAll()方法用于将多个测试语句放在一个组中执行
* 组中若有一个测试语句不通过,则这个组将会一起报错.
* 方法中第一个参数:组名称
* 方法中第二个参数:组测试语句
*/
@Test
void groupedAssertions() {
assertAll("person",
() -> assertEquals("John", person.getFirstName()),
() -> assertEquals("Doe", person.getLastName())
);
}
/**
* assertAll()方法也可以嵌套多个assertAll()方法
* 其中嵌套的多个测试组,这些组只会打印出这个组和父组的错误,对其他的组没有影响
*/
@Test
void dependentAssertions() {
assertAll("properties",
//第一个测试组
() -> {
String firstName = person.getFirstName();
assertNotNull(firstName);
assertAll("first name",
() -> assertTrue(firstName.startsWith("J")),
() -> assertTrue(firstName.endsWith("n"))
);
},
//第二个测试组
() -> {
String lastName = person.getLastName();
assertNotNull(lastName);
assertAll("last name",
() -> assertTrue(lastName.startsWith("D")),
() -> assertTrue(lastName.endsWith("e"))
);
}
);
}
/**
* assertThrows()可以用来判断lambda表达式中的代码抛出的异常
* 比如下面案例就是测试了抛出异常的信息是否相同
* 参数:
* 1:异常类声明
* 2:测试代码Lambda表达式
*/
@Test
void exceptionTesting() {
Throwable exception = assertThrows(IllegalArgumentException.class, () -> {
try {
//这里只是简单的做个测试,当然1/0不该抛IllegalArgumentException异常 ,只是简单的测试一下
int s = 1/0;
}catch (Exception e){
throw new IllegalArgumentException("a message");
}
});
assertEquals("a message", exception.getMessage());
}
/**
* assertTimeout()对方法执行时间进行测试
* 这里要借助java.time.Duration中的方法结合实现
* 实例中执行的代码部分必须在2分钟之内执行完毕,否则测试不通过
*/
@Test
void timeoutNotExceeded() {
assertTimeout(ofMinutes(2), () -> {
//执行的代码部分
});
}
/**
* assertTimeout()还可以接受一个返回值(泛型 T)
* 被测试代码如果通过测试并返回一个值,这个值被assertTimeout()方法返回
*/
@Test
void timeoutNotExceededWithResult() {
String actualResult = assertTimeout(ofMinutes(2), () -> {
return "a result";
});
assertEquals("a result", actualResult);
}
/**
* assertTimeout()毫秒案例
*/
@Test
void timeoutExceeded() {
assertTimeout(ofMillis(10), () -> {
Thread.sleep(100);
});
}
}
这里只是介绍一下其用法,其中还有好多方法没涉及到,者要等我们在使用的过程中再去查找合适的方法。
相信通过上述案例你应该对Assertions有个大体的了解, 下面再细说一下。
因为代码太长了,就不贴代码了,大家有需要可以自行查看。
里面有好多静态测试方法,每个方法又有各自的重载。
这只是截取了不到三分之一的方法。
下面通过介绍public static void assertNull(Object actual, String message)
这个判断对象为空的方法,来大致的看一下其实现过程。
public static void assertNull(Object actual, String message) {
AssertNull.assertNull(actual, message);
}
调用了AssertNull类中的assertNull方法
static void assertNull(Object actual, String message) {
if (actual != null) {
failNotNull(actual, message);
}
}
private static void failNotNull(Object actual, String message) {
AssertionUtils.fail(AssertionUtils.buildPrefix(message) + "expected: but was: <" + actual + ">", (Object)null, actual);
}
这个方法主要就是组装了错误消息,并将被验证参数传递到下一层
static void fail(String message, Object expected, Object actual) {
throw new AssertionFailedError(message, expected, actual);
}
在这里直接抛出了一个自定义异常。
到这里一个测试的过程就几乎结束了,大体来说不难,大家如果还想了解其他的方法源码,可以自己debug跟踪源码来查看。
public class AssertionFailedError extends AssertionError
--->
public class AssertionError extends Error
--->
public class Error extends Throwable
可以看书这是正常的自定义异常的模式,继承JDK自带的java.long.error类,实现自己的Error类,这里的AssertionError是所有Assertions类中方法报错的父类,其他特定的错误类就是继承的此类。
另外,在上述过程中我们知道,Assertions.assertNull()其实就是调用的AssertNull中的assertNull()实现的,我们看一下AssertNull的源码:
class AssertNull {
private AssertNull() {
}
//包可见静态方法
static void assertNull(Object actual) {
assertNull(actual, (String)null);
}
//包可见静态方法
static void assertNull(Object actual, String message) {
if (actual != null) {
failNotNull(actual, message);
}
}
//包可见静态方法
static void assertNull(Object actual, Supplier<String> messageSupplier) {
if (actual != null) {
failNotNull(actual, AssertionUtils.nullSafeGet(messageSupplier));
}
}
//类内调用方法
private static void failNotNull(Object actual, String message) {
AssertionUtils.fail(AssertionUtils.buildPrefix(message) + "expected: but was: <" + actual + ">", (Object)null, actual);
}
}
再看一下这两个类是不是在一个包中:
从源码和图片中不难发现,AssertNull中其实和Assertions一样也是提供了包内可见的静态方法 ,所以我们也可以通过引入import static org.junit.jupiter.api.AssertNull.*;
来直接使用AssertNull中的方法,不过这可不是个好想法。
Assertions将测试方法集中在该方法内,不仅便于管理,还减少代码的复杂度,性能没有任何影响,为什么要去直接使用AssertNull等类
呢,嘿嘿
最后:当然,Assertions提供的断言方法虽然多,但有时候还是不够的,当Junit5不支持你的单元测试需求时,Junit5官方还是鼓励程序员去使用第三方支持库的,比如:AssertJ、Hamcrest,Truth等。。。。
如果转载此博文,请附上本文链接:https://blog.csdn.net/csdn___lyy ,谢谢合作~
如果感觉这篇文章对您有所帮助,请点击一下“喜欢”或者“关注”博主,您的喜欢和关注将是我前进的最大动力!
refer: 官网
我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2gwn5c4zib6s0