Nếu các bạn đã thực hiện unit test với JUnit4 có một điểm yếu là không hỗ trợ parameters cho test method dẫn tới việc phải dupl code rất nhiều gây khó khăn cho việc review, update test case 👎. Điểm yếu này có thể khắc phục bằng TestNG. Rất may, JUnit5 ra đời với nhiều cải tiến, trong đó Parameterized Test là cải tiến giúp ta khắc phục được điểm yếu trên ❤️.

Required Setup
Để sử dụng Parameterized Tests ta cần dependency là junit-jupiter-params.
Với Gradle ta thêm:
| |
Với Maven ta thêm:
| |
Argument Sources
Các tham số của Parameterized Tests được cung cấp bởi các Argument Sources sau:
@ValueSource
Là cách đơn giản nhất để cung cấp data test cho Parameterized Tests. Cách này chỉ hỗ trợ các kiểu literal sau:
- short
- byte
- int
- long
- float
- double
- char
- boolean
- java.lang.String
- java.lang.Class
Ví dụ sau sẽ test hàm String.isNullOrBlank với 6 trường hợp được liệt kê ở @ValueSource:
| |
Và để test 2 trường hợp đặc biệt null và empty ta có thể sử dụng @NullSource và @EmptySource hoặc dùng @NullAndEmptySource.
@EnumSource
Để test với data test là enum. Mặc định data test là tất cả các giá trị thuộc enum. Trường hợp chỉ muốn test một vài giá trị trong enum ta có thể làm giống ví dụ.
Ví dụ kiểm tra những tháng 4, 6, 9 và 11 có 30 ngày thuộc enum Month:
| |
@MethodSource
@ValueSource và @EnumSource chỉ có thể cung cấp các data test đơn giản. Những trường hợp phức tạp ta có thể factory method để cung cấp data test. Một lưu ý là factory method phải là static.
Ví dụ này mình sẽ tối ưu so với bài Use Mock to make Unit Test easy với chỉ một test method:
| |
và data test sẽ được cung cấp qua:
| |
Lưu ý: data trả về của factory method phải là Stream của các Arguments. Tuy nhiên JUnit5 có hỗ trợ các kiểu khác như:
DoubleStreamLongStreamIntStreamCollectionIteratorIterableMột mảng của các objectsMột mảng của các primitives
@CsvSource
Data test sẽ được cung cấp bởi comma-separated values
Ví dụ sau kiểm tra hàm String.toUpperCase:
| |
@CsvFileSource
Tương tự như @CsvSource nhưng data test được load từ file.
Ví dụ sau kiểm tra hàm String.toUpperCase:
| |
với data test file:
str,expected
trile,TRILE
tRilE,TRILE
trILE,TRILE
@ArgumentsSource
Cũng tương tự như @MethodSource nhưng data test được cung cấp bởi một implements class của ArgumentsProvider thay vì một factory method. Cá nhân mình thấy @ArgumentsSource không tốt bằng
Ví dụ test input argument khác null:
| |
data test được cung cấp bởi:
| |
Customizing Display Names
Một điểm yếu của Parameterized Tests đó là hiển thị kết quả test không được rõ nghĩa lắm. Ví dụ như:
| |
sẽ trả về kết quả sau (với Gradle test report):
| Test | Method name | Duration | Result |
|---|---|---|---|
| [1] month=APRIL | test month have 30 day(Month)[1] | 0.033s | passed |
| [2] month=JUNE | test month have 30 day(Month)[2] | 0.001s | passed |
| [3] month=SEPTEMBER | test month have 30 day(Month)[3] | 0.001s | passed |
| [4] month=NOVEMBER | test month have 30 day(Month)[4] | 0.001s | passed |
nhưng sẽ hơi tối nghĩa nên mình sẽ thay đổi chút như sau:
| |
thì kết quả sẽ đẹp hơn:
| Test | Method name | Duration | Result |
|---|---|---|---|
| #1 - [APRIL] have 30 day | test month have 30 day(Month)[1] | 0.034s | passed |
| #2 - [JUNE] have 30 day | test month have 30 day(Month)[2] | 0.001s | passed |
| #3 - [SEPTEMBER] have 30 day | test month have 30 day(Month)[3] | 0.001s | passed |
| #4 - [NOVEMBER] have 30 day | test month have 30 day(Month)[4] | 0.001s | passed |
{index}là số thứ tự của các data test.{arguments}danh sách tất cả cácargument namevàargument value.{0},{1}, … làargument valuetheo thứ tự bắt đầu từ 0.