我们写好一个方法后经常希望对其单独进行测试,从前我们都是写一个main方法,在main方法中对被测试方法进行调用。这种方式相对麻烦。 Junit是一个测试框架,利用它可以在不写main方法的情况下调用被测试方法,从而对方法中的代码进行测试。
Junit要求:- 被测试方法必须为无参数、非静态、无返回值的公共(public)方法。
- 测试用类必须为public类
- 在方法上加上注解:@Test
- 导入Junit框架jar包
- 在被测试方法上执行Junit测试
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage 其中:
- JUnit Platform是在JVM上启动测试框架的基础。
- JUnit Jupiter是JUnit5扩展的新的编程模型和扩展模型,用来编写测试用例。Jupiter子项目为在平台上运行Jupiter的测试提供了一个TestEngine (测试引擎)。
- JUnit Vintage提供了一个在平台上运行JUnit 3和JUnit 4的TestEngine 。
整个Junit5可以划分成三层:顶层框架(Framework)、中间的引擎(Engine),底层的平台(Platform):
- Platform:位于架构的最底层,是JVM上执行单元测试的基础平台,还对接了各种IDE(例如IDEA、eclipse),并且还与引擎层对接,定义了引擎层对接的API;整个Junit Platform是开放的,通过引擎API各种测试框架都可以接入;
- Jupiter:位于引擎层,支持5版本的编程模型、扩展模型;是Junit5的核心,它包含了很多丰富的新特性来使JUnit自动化测试更加方便、功能更加丰富和强大。
- Vintage:位于引擎层,用于执行低版本的测试用例;是一个对JUnit3,JUnit4兼容的测试引擎,使旧版本junit的自动化测试脚本可以顺畅运行在junit5下,其实也可以看作是基于junit platform实现的接入范例。
注意:JUnit5需要JDK8或以上版本才能支持。JUnit5全面支持JDK8 lambda语法表达。
JUnit5中的Assert方法-
assertTrue/False([String message,]boolean condition); 判断一个条件是true还是false。其中
- assertTrue(boolean condition); condition:如果condition结果为true,则通过测试.
- assertFalse(boolean condition); condition:如果condition结果为false,则通过测试.
-
fail([String message,]); 失败,可以有消息,也可以没有消息。
-
assertEquals([String message,]Object expected,Object actual); 判断是否相等,可以指定输出错误信息。 第一个参数是期望值,第二个参数是实际的值。
-
assertNotEquals([String message,]Object expected,Object actual); 判断是否不相等。 第一个参数是期望值,第二个参数是实际的值。
-
assertArrayEquals([java.lang.String message,] java.lang.Object[] expecteds, java.lang.Object[] actuals) ;
-
assertNotNull/Null([String message,]Object obj); 判读一个对象是否非空(非空)。
-
assertSame/NotSame([String message,]Object expected,Object actual); 判断两个对象是否指向同一个对象。看内存地址。
-
failNotSame/failNotEquals(String message, Object expected, Object actual) 当不指向同一个内存地址或者不相等的时候,输出错误信息。 注意信息是必须的,而且这个输出是格式化过的。
-
assertThat(java.lang.String reason, java.lang.Object actual, org.hamcrest.Matcher matcher); 其中,reason为断言失败时的输出信息,actual为断言的值或对象,matcher为断言的匹配器,里面的逻辑决定了给定的actual对象满不满足断言。 (如果需要是用assertThat需要在项目中引入junit4的jar包,以及hamcrest-core.jar和hamcrest-library.jar)
说明:
- BeforeEach:被该注解修饰的方法会在每个测试方法执行前被执行一次,会被子类继承,取代低版本的Before;
- AfterEach:被该注解修饰的方法会在每个测试方法执行后被执行一次,会被子类继承,取代低版本的Before;
- BeforeAll:被该注解修饰的必须是静态方法,会在所有测试方法之前执行,会被子类继承,取代低版本的BeforeClass;
- AfterAll:被该注解修饰的必须是静态方法,会在所有测试方法执行之后才被执行,会被子类继承,取代低版本的AfterClass;
- ExtendWith:这是用来取代旧版本中的RunWith注解,不过在SpringBoot环境如果没有特别要求无需额外配置,因为SpringBootTest中已经有了;
- Test:被该注解修饰的就是测试方法;
- DisplayName:测试方法的展现名称,在测试框架中展示,支持emoji;
- Timeout:超时时长,被修饰的方法如果超时则会导致测试不通过;
- Disabled:不执行的测试方法;
Junit5中对不同测试执行阶段提供了对应的回调接口,使扩展JUnit更加方便:
回调方法描述BeforeAllCallback在@BeforeAll 注解的方法之前执行AfterAllCallback在@AfterAll 注解的方法之后执行BeforeEachCallback在@BeforeEach 注解的方法之前执行AfterEachCallback在@AfterEach 注解的方法之后执行BeforeTestExecutionCallback在测试方法运行之前执行AfterTestExecutionCallback在测试方法运行之后执行 相关Maven依赖
junit
junit
4.12
test
org.junit.jupiter
junit-jupiter
5.7.2
test
Junit5示例
import org.junit.jupiter.api.Test;
import java.time.Duration;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTimeout;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class Junit5AssertTest {
/**
* assertEquals比较两个值是否相同
*/
@Test
void fun1(){
assertEquals(2, 2);
//当不相等时,会打印出第三个参数
assertEquals(4, 5, "不相等");
}
/**
* assertTrue 判断括号里面的参数是否为true
*/
@Test
void fun2(){
assertTrue('a' assertEquals("RESEARCH", dept.getDname()),
() -> assertEquals("NEWYORK", dept.getLoc())
);
}
/**
* assertAll()方法也可以嵌套多个assertAll()方法
* 其中嵌套的多个测试组,这些组只会打印出这个组和父组的错误,对其他的组没有影响
*/
@Test
void dependentAssertions() {
assertAll("properties",
//第一个测试组
() -> {
String dname = dept.getDname();
assertNotNull(dname);
assertAll("dname",
() -> assertTrue(dname.startsWith("R")),
() -> assertTrue(dname.endsWith("H"))
);
},
//第二个测试组
() -> {
String loc = dept.getLoc();
assertNotNull(loc);
assertAll("loc",
() -> assertTrue(loc.startsWith("N")),
() -> assertTrue(loc.endsWith("k"))
);
}
);
}
/**
* assertThrows()可以用来判断lambda表达式中的代码抛出的异常
* 比如下面案例就是测试了抛出异常的信息是否相同
* 参数:
* 1:异常类声明
* 2:测试代码Lambda表达式
*/
@Test
void exceptionTesting() {
Throwable exception = assertThrows(IllegalArgumentException.class, () -> {
try {
System.out.println(1 / 0);
}catch (Exception e){
throw new IllegalArgumentException("非法的参数异常");
}
});
assertEquals("非法的参数异常", exception.getMessage());
}
/**
* assertTimeout()对方法执行时间进行测试
* 实例中执行的代码部分必须在2分钟之内执行完毕,否则测试不通过
*/
@Test
void timeoutNotExceeded() {
assertTimeout(Duration.ofMinutes(2), () -> {
System.out.println(33+44);
});
}
/**
* assertTimeout()还可以接受一个返回值(泛型 T)
* 被测试代码如果通过测试就返回一个值,这个值被assertTimeout()方法返回
*/
@Test
void timeoutNotExceededWithResult() {
String actualResult = assertTimeout(Duration.ofMinutes(2), () -> {
return "haha";
});
assertEquals("haha", actualResult);
}
/**
* assertTimeout()毫秒案例
*/
@Test
void timeoutExceeded() {
assertTimeout(Duration.ofMillis(10), () -> {
Thread.sleep(100);
});
}
}
SpringBoot中使用Junit
Junit4单元测试类写法:
@SpringBootTest
public class SpringDataES {
}
Junit5单元测试类写法:
@SpringBootTest
public class SpringDataES {
}
Junit5中RunWith注解已经被ExtendWith取代,而SpringBootTest注解,已经包含了ExtendWith: