Junit5是Junit一個(gè)非常大的改進(jìn)版本磷账,根據(jù)Junit5官方文檔上的描述:
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
- JUnit Platform:提供了在JVM上啟動(dòng)測(cè)試框架的基礎(chǔ),包括Junit核心的API等等闽坡。
- JUnit Jupiter:提供了用于編寫測(cè)試代碼的新的編程和擴(kuò)展模型。
- JUnit Vintage:提供了使用JUnit3和4編寫測(cè)試方法的兼容流码。
相比于之前Junit4行施,個(gè)人感覺在使用上比較大的一個(gè)改進(jìn)是在參數(shù)化測(cè)試這塊,本來很多的測(cè)試場(chǎng)景要寫的重復(fù)場(chǎng)景就比較多若锁,通過參數(shù)化測(cè)試搁骑,可以大量減少測(cè)試的編寫斧吐。
比如用經(jīng)典的FizzBuzz
來進(jìn)行練習(xí).
@Data
public class FizzBuzz {
public String say(int number) {
if (isMultiple(number, 3) && isMultiple(number, 5)) {
return "fizzbuzz";
}
if (isMultiple(number, 3)) {
return "fizz";
}
if (isMultiple(number, 5)) {
return "buzz";
}
return "hello";
}
private boolean isMultiple(int number, int i) {
return number % i == 0;
}
}
如果想寫一個(gè)測(cè)試來覆蓋所有的邏輯又固,按照原來Junit4的方法仲器,要寫四個(gè)方法來覆蓋這些邏輯,但是再Junit5中可以用注解來解決這個(gè)問題仰冠。
public class Junit5Test {
@DisplayName("FizzBuzz Practice")
@ParameterizedTest(name = "number {0} say {1}")
@CsvSource({
" '1', 'hello' ",
" '3', 'fizz' ",
" '5', 'buzz' ",
" '15', 'fizzbuzz' "
})
public void test(int number, String result) {
FizzBuzz fizzBuzz = new FizzBuzz();
String say = fizzBuzz.say(number);
Assertions.assertEquals(result, say);
}
}
通過@CsvSource
注解(還有其他的XXXXSource
注解)來進(jìn)行參數(shù)化的測(cè)試乏冀,這個(gè)函數(shù)會(huì)根據(jù)參數(shù)進(jìn)行多次執(zhí)行,確保將代碼邏輯的分支都盡量覆蓋到洋只。
好用的Junit插件和測(cè)試工具
這里介紹幾個(gè)我平時(shí)會(huì)用到的Junit5擴(kuò)展插件辆沦,在這些插件的加持下,測(cè)試代碼會(huì)寫的簡(jiǎn)單很多识虚。
- https://github.com/junit-pioneer/junit-pioneer
- https://github.com/joshka/junit-json-params
- https://github.com/j-easy/easy-random
第一個(gè)介紹的是junit-pioneer
肢扯,在測(cè)試中經(jīng)常會(huì)碰到使用一些對(duì)入?yún)⑴帕薪M合使用的情況,使用junit-pioneer
這個(gè)插件担锤,可以幫助我們比較輕松地應(yīng)對(duì)這種情況蔚晨。
public class CombinationTest {
@CartesianProductTest
@CartesianValueSource(strings = {"type1", "type2"})
@CartesianValueSource(strings = {"action A", "action B"})
public void combinationTest(String type, String action) {
System.out.printf("%s --> %s \n", type, action);
}
}
執(zhí)行的效果:
type1 --> action A
type1 --> action B
type2 --> action A
type2 --> action B
junit-pioneer
包含了很多對(duì)Junit5的擴(kuò)展,有興趣的話肛循,可以在它的文檔中繼續(xù)探索他的一些功能:https://junit-pioneer.org/docs/
第二個(gè)插件是junit-json-params
, 這個(gè)插件
public class JsonTest {
@ParameterizedTest
@JsonSource("[{\"key\":\"value1\"},{\"key\":\"value2\"}]")
@DisplayName("provides an array of objects")
void arrayOfObjects(JsonObject object) {
Assertions.assertTrue(object.getString("key").startsWith("value"));
}
}
第三個(gè)推薦的是一個(gè)對(duì)象生成器框架Easy Random
铭腕,在編寫測(cè)試過程中,組裝對(duì)象通常是一個(gè)非常費(fèi)勁的事情多糠,很多參數(shù)也用不到累舷,通過Easy Random
可以快速組裝出一個(gè)隨機(jī)對(duì)象。
public class ObjectRandomTest {
@Test
public void test(){
Book book = new EasyRandom().nextObject(Book.class);
Assertions.assertNotNull(book.getBookName());
Assertions.assertNotNull(book.getAuthor());
}
@Data
static class Book {
private String bookName;
private String author;
}
}
Maven中的POM
以下是剛剛提到的這些框架在Maven中的配置夹孔,另外重復(fù)的注解這種寫法(junit-pioneer
用到了)只有Java8以及以上的版本才支持被盈,所以maven中編譯的版本一定要在1.8以上。
<properties>
<junit.jupiter.version>5.7.1</junit.jupiter.version>
<junit.platform.version>1.7.1</junit.platform.version>
<junit-pioneer.version>1.3.8</junit-pioneer.version>
<junit-json-params.version>5.6.2-r0</junit-json-params.version>
<javax.json.version>1.1.3</javax.json.version>
<easy-random-core.version>4.3.0</easy-random-core.version>
<lombok.version>1.18.20</lombok.version>
</properties>
<dependencies>
<!--junit5-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit-pioneer</groupId>
<artifactId>junit-pioneer</artifactId>
<version>${junit-pioneer.version}</version>
<scope>test</scope>
</dependency>
<!--/junit5-->
<!--json plugin dependency-->
<dependency>
<groupId>net.joshka</groupId>
<artifactId>junit-json-params</artifactId>
<version>${junit-json-params.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>${javax.json.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>${javax.json.version}</version>
</dependency>
<!--/json plugin dependency-->
<!--EasyRandom-->
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-random-core</artifactId>
<version>${easy-random-core.version}</version>
</dependency>
<!--/EasyRandom-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>