Junit5是Junit一個非常大的改進版本,根據Junit5官方文檔上的描述:
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
- JUnit Platform:提供了在JVM上啓動測試框架的基礎,包括Junit核心的API等等。
- JUnit Jupiter:提供了用於編寫測試代碼的新的編程和擴展模型。
- JUnit Vintage:提供了使用JUnit3和4編寫測試方法的兼容。
相比於之前Junit4,個人感覺在使用上比較大的一個改進是在參數化測試這塊,本來很多的測試場景要寫的重複場景就比較多,通過參數化測試,可以大量減少測試的編寫。
比如用經典的FizzBuzz
來進行練習.
@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;
}
}
如果想寫一個測試來覆蓋所有的邏輯,按照原來Junit4的方法,要寫四個方法來覆蓋這些邏輯,但是再Junit5中可以用註解來解決這個問題。
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
註解)來進行參數化的測試,這個函數會根據參數進行多次執行,確保將代碼邏輯的分支都儘量覆蓋到。
好用的Junit插件和測試工具
這裏介紹幾個我平時會用到的Junit5擴展插件,在這些插件的加持下,測試代碼會寫的簡單很多。
- https://github.com/junit-pioneer/junit-pioneer
- https://github.com/joshka/junit-json-params
- https://github.com/j-easy/easy-random
第一個介紹的是junit-pioneer
,在測試中經常會碰到使用一些對入參排列組合使用的情況,使用junit-pioneer
這個插件,可以幫助我們比較輕鬆地應對這種情況。
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);
}
}
執行的效果:
type1 --> action A
type1 --> action B
type2 --> action A
type2 --> action B
junit-pioneer
包含了很多對Junit5的擴展,有興趣的話,可以在它的文檔中繼續探索他的一些功能:https://junit-pioneer.org/docs/
第二個插件是junit-json-params
, 這個插件
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"));
}
}
第三個推薦的是一個對象生成器框架Easy Random
,在編寫測試過程中,組裝對象通常是一個非常費勁的事情,很多參數也用不到,通過Easy Random
可以快速組裝出一個隨機對象。
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中的配置,另外重複的註解這種寫法(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>