JUnit là một framework tiêu chuẩn cho kiểm thử đơn vị trong hệ sinh thái Java và Kotlin, được sử dụng trong phát triển Android để xác minh logic kinh doanh ở cấp độ các thành phần độc lập. Framework cung cấp một tập hợp các chú thích, phương thức khẳng định và Test Runner để tự động phát hiện và thực thi các bài kiểm thử. Theo JUnit.org, thư viện này vẫn là giải pháp phổ biến nhất cho kiểm thử đơn vị trong hệ sinh thái JVM: hơn 70% các dự án Java sử dụng JUnit ở bất kỳ phiên bản nào.
Những điểm chính
JUnit là một framework mã nguồn mở để viết và chạy các kiểm thử đơn vị có thể lặp lại trong Java và Kotlin. Nó là một phần của hệ sinh thái xUnit, một họ các framework dựa trên kiến trúc của Kent Beck và Erich Gamma, và là công cụ kiểm thử tiêu chuẩn trong Android Studio và IntelliJ IDEA.
Nhiệm vụ chính của JUnit là cô lập một đoạn mã nhỏ (phương thức, lớp) và xác minh hành vi của nó trong các điều kiện được kiểm soát. Các kiểm thử được viết dưới dạng các lớp Java/Kotlin thông thường với các chú thích, và framework đảm nhận việc phát hiện kiểm thử, quản lý vòng đời và thu thập thống kê thực thi.
Phiên bản đầu tiên của JUnit xuất hiện vào năm 1997 và đã thay đổi triệt để cách tiếp cận phát triển bằng cách phổ biến các thực hành Phát triển hướng kiểm thử (TDD). Ngày nay, JUnit 5 (Jupiter) là phiên bản hiện tại, được thiết kế lại hoàn toàn với kiến trúc mô-đun hỗ trợ Java 8+ và các tiện ích mở rộng.
Cơ chế thực thi của JUnit dựa trên mẫu Test Runner, quét classpath, tìm các phương thức có chú thích @Test, tạo một thể hiện của lớp kiểm thử và chạy các phương thức theo một thứ tự cụ thể. Test Runner quản lý vòng đời: BeforeAll → BeforeEach → Test → AfterEach → AfterAll.
JUnit bao bọc mỗi phương thức kiểm thử trong một thể hiện lớp riêng biệt, đảm bảo sự cô lập giữa các kiểm thử. Điều này có nghĩa là các trường của lớp không giữ trạng thái giữa các phương thức @Test khác nhau — mỗi kiểm thử bắt đầu với một đối tượng sạch.
Kiểm thử đơn giản nhất trong JUnit là một phương thức có chú thích @Test gọi mã đang được kiểm thử và xác minh kết quả thông qua một khẳng định. Nếu khẳng định thất bại, kiểm thử được coi là thất bại và JUnit báo cáo lỗi.
@Test
void additionShouldReturnCorrectSum() {
var calculator = new Calculator();
var result = calculator.add(2, 3);
assertEquals(5, result);
}
Test Runner tự động tìm phương thức như vậy, chạy nó và báo cáo kết quả. Nếu phương thức không ném ngoại lệ — kiểm thử thành công (green). Nếu một khẳng định thất bại — kiểm thử thất bại (red).
Các chú thích trong JUnit xác định thời điểm và cách thức mã kiểm thử nên thực thi. Trong JUnit 5, các chú thích nằm trong gói org.junit.jupiter.api và bao gồm tất cả các giai đoạn: chuẩn bị dữ liệu, thực thi kiểm thử, dọn dẹp tài nguyên.
| Chú thích | Mục đích | Thực thi |
|---|---|---|
| @Test | Đánh dấu phương thức kiểm thử | Một lần mỗi lần gọi |
| @BeforeEach | Thiết lập trước mỗi kiểm thử | Trước mỗi @Test |
| @BeforeAll | Khởi tạo lớp một lần | Một lần trước tất cả kiểm thử |
| @AfterEach | Dọn dẹp sau mỗi kiểm thử | Sau mỗi @Test |
| @AfterAll | Kết thúc lớp một lần | Một lần sau tất cả kiểm thử |
| @DisplayName | Tên kiểm thử dễ đọc | Trang trí |
Hãy xem xét một lớp kiểm thử hoàn chỉnh với vòng đời phù hợp. Phương thức setUp tạo một thể hiện Calculator mới trước mỗi kiểm thử, và tearDown giải phóng tài nguyên — ví dụ, đóng các bộ mô tả tệp hoặc kết nối cơ sở dữ liệu.
class CalculatorTest {
private Calculator calculator;
@BeforeEach
void setUp() {
calculator = new Calculator();
}
@Test
void subtractionShouldReturnCorrectResult() {
int result = calculator.subtract(10, 4);
assertEquals(6, result);
}
@AfterEach
void tearDown() {
calculator.reset();
}
}
Các khẳng định là các phương thức tĩnh so sánh kết quả thực tế với kết quả mong đợi và ném ngoại lệ nếu không khớp. JUnit 5 cung cấp lớp org.junit.jupiter.api.Assertions với hơn 25 phương thức cho các kịch bản xác minh khác nhau — từ so sánh giá trị đơn giản đến kiểm tra thời gian chờ và các khẳng định nhóm.
Phương thức assertThrows đáng được chú ý đặc biệt, vì nó cho phép xác minh rằng mã xử lý chính xác các tình huống lỗi — chia cho không, truyền null, vượt quá giới hạn.
@Test
void divisionByZeroShouldThrowException() {
Calculator calc = new Calculator();
ArithmeticException exception = assertThrows(
ArithmeticException.class,
() -> calc.divide(10, 0)
);
assertEquals("Cannot divide by zero", exception.getMessage());
}
Kiểm thử tham số hóa cho phép chạy cùng một phương thức kiểm thử với các bộ đối số khác nhau. Trong JUnit 5, điều này được thực hiện bằng cách sử dụng chú thích @ParameterizedTest kết hợp với một nguồn dữ liệu — @ValueSource, @CsvSource, @MethodSource hoặc @EnumSource.
Cách tiếp cận này giảm triệt để sự trùng lặp mã: thay vì mười kiểm thử giống hệt nhau cho các giá trị khác nhau, bạn viết một phương thức tham số hóa duy nhất. Theo Google Testing Blog, tham số hóa giảm khối lượng mã kiểm thử từ 40–60% mà không mất đi độ phủ.
Chú thích @CsvSource truyền nhiều dòng được phân tách bằng dấu phẩy vào kiểm thử. Mỗi dòng tương ứng với một lần chạy kiểm thử. JUnit tự động chuyển đổi các giá trị chuỗi thành các kiểu cần thiết: int, long, String và các kiểu khác.
@ParameterizedTest
@CsvSource({
"1, 1, 2",
"2, 3, 5",
"10, 20, 30",
"-1, 1, 0"
})
void additionWithMultipleInputs(int a, int b, int expected) {
assertEquals(expected, a + b);
}
Khi dữ liệu đầu vào phức tạp hơn các số hoặc chuỗi đơn giản, @MethodSource được sử dụng. Nó tham chiếu đến một phương thức tĩnh trả về một Stream các đối số — ví dụ: một Stream các Arguments hoặc một Stream các đối tượng User để kiểm thử lớp DAO.
Trong phát triển Android, JUnit được sử dụng cùng với AndroidX Test, cung cấp các tiện ích mở rộng để kiểm thử Activity, Content Provider và các thành phần Android khác. JUnit đảm nhận các kiểm thử đơn vị được thực thi trên JVM mà không cần trình giả lập, trong khi AndroidX Test đảm nhận các kiểm thử công cụ trên thiết bị.
Để thêm JUnit 5 vào một dự án Android, chỉ cần bao gồm phụ thuộc org.junit.jupiter:junit-jupiter trong build.gradle cấp mô-đun. Plugin AGP Gradle hỗ trợ chạy các kiểm thử JUnit 5 trên JVM thông qua Test Runner tiêu chuẩn.
// build.gradle.kts
android {
testOptions {
unitTests.isIncludeAndroidResources = true
}
}
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:5.11.0")
testImplementation("androidx.test:core-ktx:1.6.1")
}
Trong thực tế, JUnit thường được sử dụng nhất để kiểm thử ViewModel và các kho lưu trữ — các lớp không yêu cầu ngữ cảnh Android hoặc trình giả lập. Một kiểm thử như vậy chạy trong mili giây và có thể được thực thi hàng trăm lần mà không mất thời gian.
JUnit 5 (Jupiter) không chỉ là một phiên bản mới, mà là một nền tảng được thiết kế lại hoàn toàn chia thành ba mô-đun: JUnit Platform (thực thi kiểm thử trên JVM), JUnit Jupiter (API để viết kiểm thử) và JUnit Vintage (tương thích ngược với JUnit 4). Tính mô-đun này cho phép kết nối các Test Engine khác nhau — ví dụ: Spek cho Kotlin hoặc TestNG.
| Đặc điểm | JUnit 4 | JUnit 5 |
|---|---|---|
| Gói | org.junit | org.junit.jupiter |
| Chú thích cơ bản | @Test (từ junit.framework) | @Test (từ org.junit.jupiter.api) |
| Before/After | @Before, @After, @BeforeClass | @BeforeEach, @AfterEach, @BeforeAll |
| Tham số hóa | @RunWith(Parameterized.class) | @ParameterizedTest + @ValueSource |
| Tiện ích mở rộng | @Rule, @ClassRule | @ExtendWith, API linh hoạt hơn |
| Java tối thiểu | Java 5 | Java 8+ |
Di chuyển từ JUnit 4 sang JUnit 5 không yêu cầu viết lại tất cả các kiểm thử — chỉ cần thêm JUnit Vintage Engine và các kiểm thử cũ sẽ tiếp tục hoạt động. Các kiểm thử mới được khuyến nghị viết bằng JUnit 5 để tận dụng các tiện ích mở rộng, khẳng định lambda và hỗ trợ tham số hóa tích hợp sẵn.
Câu hỏi thường gặp
JUnit là một framework để viết và chạy các kiểm thử, trong khi Mockito là một thư viện để tạo các đối tượng mock. Chúng được sử dụng cùng nhau: JUnit quản lý việc thực thi kiểm thử và Mockito thay thế các phụ thuộc của lớp được kiểm thử.
Có, JUnit 5 hoàn toàn tương thích với các dự án Android. Đối với kiểm thử đơn vị, chỉ cần thêm phụ thuộc junit-jupiter trong build.gradle. Các kiểm thử công cụ vẫn hoạt động thông qua AndroidX Test Runner.
Tối thiểu, một chú thích @Test duy nhất trước phương thức là đủ. @BeforeEach và @AfterEach được khuyến nghị để khởi tạo và dọn dẹp, nhưng không bắt buộc.
Test Runner là một thành phần của JUnit quét classpath, tìm các phương thức có chú thích @Test, tạo các thể hiện của lớp kiểm thử và chạy các kiểm thử. Trong JUnit 5, vai trò này được thực hiện bởi JUnit Platform với các Test Engine được kết nối.
Sử dụng assertThrows(Class, Executable) — nó nhận loại ngoại lệ mong đợi và một lambda với lời gọi phương thức. JUnit xác minh rằng ngoại lệ thực sự đã được ném và trả về nó để kiểm tra thêm.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm