JUnit: คืออะไร แนวคิดหลัก และ工作原理

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-04-08 เวลาอ่าน: 8 นาที

JUnit เป็นเฟรมเวิร์กมาตรฐานสำหรับการทดสอบหน่วยในระบบนิเวศ Java และ Kotlin ซึ่งใช้ในการพัฒนา Android เพื่อตรวจสอบตรรกะทางธุรกิจในระดับของคอมโพเนนต์ที่แยกออกจากกัน เฟรมเวิร์กมีชุดของคำอธิบายประกอบ เมธอดการยืนยัน และ Test Runner สำหรับการค้นหาและดำเนินการทดสอบโดยอัตโนมัติ ตามข้อมูลจาก JUnit.org ไลบรารียังคงเป็นโซลูชันยอดนิยมที่สุดสำหรับการทดสอบหน่วยในระบบนิเวศ JVM: โปรเจกต์ Java กว่า 70% ใช้ JUnit ในเวอร์ชันใดเวอร์ชันหนึ่ง

ประเด็นสำคัญ

  • JUnit เป็นเฟรมเวิร์กโอเพนซอร์สสำหรับการทดสอบหน่วยของโค้ด Java และ Kotlin
  • คำอธิบายประกอบ — @Test, @BeforeEach, @BeforeAll จัดการวงจรชีวิตของคลาสทดสอบ
  • การยืนยัน — assertEquals, assertTrue, assertThrows ตรวจสอบผลลัพธ์การดำเนินการที่คาดหวัง
  • การทดสอบแบบกำหนดพารามิเตอร์ — อนุญาตให้เรียกใช้การทดสอบเดียวด้วยชุดข้อมูลป้อนเข้าที่แตกต่างกัน
  • Test Runner — โครงสร้างพื้นฐานของ JUnit จะค้นหาและเรียกใช้การทดสอบทั้งหมดในโปรเจกต์โดยอัตโนมัติ

JUnit คืออะไร?

JUnit เป็นเฟรมเวิร์กโอเพนซอร์สสำหรับเขียนและเรียกใช้การทดสอบหน่วยที่ทำซ้ำได้ใน Java และ Kotlin เป็นส่วนหนึ่งของระบบนิเวศ xUnit ซึ่งเป็นตระกูลของเฟรมเวิร์กที่อิงตามสถาปัตยกรรมของ Kent Beck และ Erich Gamma และเป็นเครื่องมือทดสอบมาตรฐานใน Android Studio และ IntelliJ IDEA

งานหลักของ JUnit คือการแยกส่วนย่อยของโค้ด (เมธอด, คลาส) และตรวจสอบพฤติกรรมของมันภายใต้สภาวะที่ควบคุม การทดสอบถูกเขียนเป็นคลาส Java/Kotlin ปกติพร้อมคำอธิบายประกอบ และเฟรมเวิร์กจะจัดการการค้นหาการทดสอบ การจัดการวงจรชีวิต และการรวบรวมสถิติการดำเนินการ

JUnit เวอร์ชันแรกปรากฏในปี 1997 และเปลี่ยนแปลงแนวทางการพัฒนาอย่างสิ้นเชิงโดยทำให้แนวปฏิบัติ Test-Driven Development (TDD) เป็นที่นิยม ปัจจุบัน JUnit 5 (Jupiter) เป็นเวอร์ชันปัจจุบัน ซึ่งออกแบบใหม่ทั้งหมดด้วยสถาปัตยกรรมแบบโมดูลาร์ที่รองรับ Java 8+ และส่วนขยาย

JUnit ทำงานอย่างไร

กลไก การทำงานของ JUnit ขึ้นอยู่กับรูปแบบ Test Runner ซึ่งสแกน classpath ค้นหาเมธอดที่มีคำอธิบายประกอบ @Test สร้างอินสแตนซ์ของคลาสทดสอบ และเรียกใช้เมธอดในลำดับที่กำหนด Test Runner จัดการวงจรชีวิต: BeforeAll → BeforeEach → Test → AfterEach → AfterAll

วงจรชีวิตของคลาสทดสอบ

JUnit ห่อแต่ละเมธอดทดสอบในอินสแตนซ์คลาสแยกต่างหาก ซึ่งรับประกัน การแยกส่วน ระหว่างการทดสอบ ซึ่งหมายความว่าฟิลด์ของคลาสจะไม่เก็บสถานะระหว่างเมธอด @Test ที่แตกต่างกัน — การทดสอบแต่ละครั้งเริ่มต้นด้วยวัตถุที่สะอาด

โครงสร้างพื้นฐานของการทดสอบ

การทดสอบที่ง่ายที่สุดใน JUnit คือเมธอดที่มีคำอธิบายประกอบ @Test ซึ่งเรียกใช้โค้ดที่อยู่ภายใต้การทดสอบและตรวจสอบผลลัพธ์ผ่าน การยืนยัน หากการยืนยันล้มเหลว การทดสอบจะถือว่าล้มเหลวและ JUnit จะรายงานข้อผิดพลาด

java
@Test
void additionShouldReturnCorrectSum() {
    var calculator = new Calculator();
    var result = calculator.add(2, 3);
    assertEquals(5, result);
}

Test Runner จะค้นหาเมธอดดังกล่าวโดยอัตโนมัติ เรียกใช้และรายงานผลลัพธ์ หากเมธอดไม่โยนข้อยกเว้น — การทดสอบผ่าน (green) หากการยืนยันล้มเหลว — การทดสอบล้มเหลว (red)

คำอธิบายประกอบ JUnit: วงจรชีวิตการทดสอบ

คำอธิบายประกอบ ใน JUnit กำหนดว่าเมื่อใดและอย่างไรที่โค้ดทดสอบควรดำเนินการ ใน JUnit 5 คำอธิบายประกอบอยู่ในแพ็คเกจ org.junit.jupiter.api และครอบคลุมทุกขั้นตอน: การเตรียมข้อมูล การดำเนินการทดสอบ การทำความสะอาดทรัพยากร

คำอธิบายประกอบวัตถุประสงค์การดำเนินการ
@Testระบุเมธอดทดสอบหนึ่งครั้งต่อการเรียก
@BeforeEachการตั้งค่าก่อนการทดสอบแต่ละครั้งก่อนแต่ละ @Test
@BeforeAllการเริ่มต้นคลาสครั้งเดียวหนึ่งครั้งก่อนการทดสอบทั้งหมด
@AfterEachการทำความสะอาดหลังการทดสอบแต่ละครั้งหลังแต่ละ @Test
@AfterAllการสิ้นสุดคลาสครั้งเดียวหนึ่งครั้งหลังการทดสอบทั้งหมด
@DisplayNameชื่อการทดสอบที่มนุษย์อ่านได้การตกแต่ง

ตัวอย่างการใช้คำอธิบายประกอบ

พิจารณาคลาสทดสอบสมบูรณ์ที่มีวงจรชีวิตที่เหมาะสม เมธอด setUp สร้างอินสแตนซ์ Calculator ใหม่ก่อนการทดสอบแต่ละครั้ง และ tearDown ปลดปล่อยทรัพยากร — ตัวอย่างเช่น การปิดตัวบอกตำแหน่งไฟล์หรือการเชื่อมต่อฐานข้อมูล

java
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();
    }
}

การยืนยัน: การตรวจสอบผลลัพธ์ใน JUnit

การยืนยัน เป็นเมธอดแบบสแตติกที่เปรียบเทียบผลลัพธ์จริงกับผลลัพธ์ที่คาดหวังและโยนข้อยกเว้นหากไม่ตรงกัน JUnit 5 มีคลาส org.junit.jupiter.api.Assertions พร้อมเมธอดมากกว่า 25 เมธอดสำหรับสถานการณ์การตรวจสอบที่หลากหลาย ตั้งแต่การเปรียบเทียบค่าง่ายไปจนถึงการตรวจสอบหมดเวลาและการยืนยันแบบกลุ่ม

  • assertEquals(expected, actual) — ตรวจสอบความเท่าเทียมกันผ่าน equals()
  • assertTrue(condition) — ตรวจสอบว่าเงื่อนไขเป็นจริง
  • assertFalse(condition) — ตรวจสอบว่าเงื่อนไขเป็นเท็จ
  • assertNotNull(object) — ตรวจสอบว่าวัตถุไม่เป็น null
  • assertNull(object) — ตรวจสอบว่าวัตถุเป็น null
  • assertThrows(exception, executable) — ตรวจสอบว่าโค้ดโยนข้อยกเว้นที่ระบุ
  • assertAll(executables) — จัดกลุ่มการยืนยันหลายรายการและดำเนินการทั้งหมดโดยไม่หยุดที่ความล้มเหลวแรก

assertThrows สำหรับการตรวจสอบข้อยกเว้น

เมธอด assertThrows สมควรได้รับความสนใจเป็นพิเศษ เพราะช่วยให้ตรวจสอบได้ว่าโค้ดจัดการกับสถานการณ์ข้อผิดพลาดอย่างถูกต้อง — การหารด้วยศูนย์ การส่ง null การเกินขีดจำกัด

java
@Test
void divisionByZeroShouldThrowException() {
    Calculator calc = new Calculator();

    ArithmeticException exception = assertThrows(
        ArithmeticException.class,
        () -> calc.divide(10, 0)
    );

    assertEquals("Cannot divide by zero", exception.getMessage());
}

การทดสอบแบบกำหนดพารามิเตอร์ใน JUnit

การทดสอบแบบกำหนดพารามิเตอร์ อนุญาตให้เรียกใช้เมธอดทดสอบเดียวกันด้วยชุดอาร์กิวเมนต์ที่แตกต่างกัน ใน JUnit 5 ทำได้โดยใช้คำอธิบายประกอบ @ParameterizedTest ร่วมกับแหล่งข้อมูล — @ValueSource, @CsvSource, @MethodSource หรือ @EnumSource

วิธีการนี้ลดการทำซ้ำโค้ดอย่างสิ้นเชิง: แทนที่จะเขียนการทดสอบที่เหมือนกันสิบรายการสำหรับค่าที่แตกต่างกัน จะเขียนเมธอดแบบกำหนดพารามิเตอร์เพียงเมธอดเดียว ตาม Google Testing Blog การกำหนดพารามิเตอร์ช่วยลดปริมาณโค้ดทดสอบลง 40–60% โดยไม่สูญเสียความครอบคลุม

ตัวอย่างกับ CsvSource

คำอธิบายประกอบ @CsvSource ส่งหลายแถวที่คั่นด้วยเครื่องหมายจุลภาคไปยังการทดสอบ แต่ละแถวสอดคล้องกับการเรียกใช้การทดสอบหนึ่งครั้ง JUnit แปลงค่าสตริงเป็นประเภทที่ต้องการโดยอัตโนมัติ: int, long, String และอื่นๆ

java
@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);
}

MethodSource สำหรับวัตถุที่ซับซ้อน

เมื่อข้อมูลป้อนเข้าซับซ้อนกว่าตัวเลขหรือสตริงธรรมดา จะใช้ @MethodSource ซึ่งอ้างอิงถึงเมธอดแบบสแตติกที่ส่งคืน Stream ของอาร์กิวเมนต์ — ตัวอย่างเช่น Stream ของ Arguments หรือ Stream ของวัตถุ User สำหรับการทดสอบชั้น DAO

การรวม JUnit กับโปรเจกต์ Android

ในการพัฒนา Android JUnit ถูกใช้ร่วมกับ AndroidX Test ซึ่งมีส่วนขยายสำหรับการทดสอบ Activity, Content Provider และคอมโพเนนต์ Android อื่นๆ JUnit จัดการการทดสอบหน่วยที่ทำงานบน JVM โดยไม่ต้องใช้โปรแกรมจำลอง ในขณะที่ AndroidX Test จัดการการทดสอบที่ใช้เครื่องมือบนอุปกรณ์

การตั้งค่า Gradle

เพื่อเพิ่ม JUnit 5 ในโปรเจกต์ Android เพียงเพิ่มการพึ่งพา org.junit.jupiter:junit-jupiter ใน build.gradle ระดับโมดูล ปลั๊กอิน AGP Gradle รองรับการเรียกใช้การทดสอบ JUnit 5 บน JVM ผ่าน Test Runner มาตรฐาน

kotlin
// 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")
}

การทดสอบ ViewModel ด้วย JUnit

ในทางปฏิบัติ JUnit มักใช้สำหรับการทดสอบ ViewModel และพื้นที่เก็บข้อมูล — ชั้นที่ไม่ต้องการบริบท Android หรือโปรแกรมจำลอง การทดสอบดังกล่าวทำงานในหน่วยมิลลิวินาทีและสามารถดำเนินการได้หลายร้อยครั้งโดยไม่เสียเวลา

  • ViewModel — การตรวจสอบสถานะ: loading, success, error
  • Repository — การตรวจสอบการแมปข้อมูลและการจัดการข้อผิดพลาด
  • UseCase — การตรวจสอบตรรกะทางธุรกิจด้วยม็อคของการพึ่งพา

JUnit 4 vs JUnit 5: ความแตกต่างหลัก

JUnit 5 (Jupiter) ไม่ใช่แค่เวอร์ชันใหม่ แต่เป็นแพลตฟอร์มที่ออกแบบใหม่ทั้งหมดแบ่งออกเป็นสามโมดูล: JUnit Platform (การดำเนินการทดสอบบน JVM), JUnit Jupiter (API สำหรับเขียนการทดสอบ) และ JUnit Vintage (ความเข้ากันได้ย้อนหลังกับ JUnit 4) ความเป็นโมดูลาร์นี้ช่วยให้สามารถเชื่อมต่อ Test Engine ที่แตกต่างกัน — ตัวอย่างเช่น Spek สำหรับ Kotlin หรือ TestNG

คุณลักษณะJUnit 4JUnit 5
แพ็คเกจorg.junitorg.junit.jupiter
คำอธิบายประกอบพื้นฐาน@Test (จาก junit.framework)@Test (จาก org.junit.jupiter.api)
Before/After@Before, @After, @BeforeClass@BeforeEach, @AfterEach, @BeforeAll
กำหนดพารามิเตอร์@RunWith(Parameterized.class)@ParameterizedTest + @ValueSource
ส่วนขยาย@Rule, @ClassRule@ExtendWith, API ที่ยืดหยุ่นกว่า
Java ขั้นต่ำJava 5Java 8+

การย้ายจาก JUnit 4 ไป JUnit 5 ไม่จำเป็นต้องเขียนการทดสอบทั้งหมดใหม่ — เพียงเพิ่ม JUnit Vintage Engine และการทดสอบเก่าจะยังคงทำงานได้ การทดสอบใหม่แนะนำให้เขียนด้วย JUnit 5 เพื่อใช้ประโยชน์จากส่วนขยาย การยืนยันแบบแลมบ์ดา และการสนับสนุน การกำหนดพารามิเตอร์ ในตัว

คำถามที่พบบ่อย

JUnit แตกต่างจาก Mockito อย่างไร?

JUnit เป็นเฟรมเวิร์กสำหรับเขียนและเรียกใช้การทดสอบ ในขณะที่ Mockito เป็นไลบรารีสำหรับสร้างวัตถุจำลอง พวกมันถูกใช้ร่วมกัน: JUnit จัดการการดำเนินการทดสอบ และ Mockito แทนที่การพึ่งพาของคลาสที่อยู่ภายใต้การทดสอบ

สามารถใช้ JUnit 5 ในโปรเจกต์ Android ได้หรือไม่?

ได้ JUnit 5 เข้ากันได้อย่างสมบูรณ์กับโปรเจกต์ Android สำหรับการทดสอบหน่วย เพียงเพิ่มการพึ่งพา junit-jupiter ใน build.gradle การทดสอบที่ใช้เครื่องมือยังคงทำงานผ่าน AndroidX Test Runner

ชุดคำอธิบายประกอบขั้นต่ำที่จำเป็นสำหรับการทดสอบคืออะไร?

อย่างน้อยที่สุด คำอธิบายประกอบ @Test เพียงตัวเดียวก่อนเมธอดก็เพียงพอแล้ว @BeforeEach และ @AfterEach แนะนำสำหรับการเริ่มต้นและการทำความสะอาด แต่ไม่จำเป็น

Test Runner ใน JUnit คืออะไร?

Test Runner เป็นคอมโพเนนต์ของ JUnit ที่สแกน classpath ค้นหาเมธอดที่มีคำอธิบายประกอบ @Test สร้างอินสแตนซ์ของคลาสทดสอบและเรียกใช้การทดสอบ ใน JUnit 5 บทบาทนี้ดำเนินการโดย JUnit Platform พร้อมกับ Test Engine ที่เชื่อมต่อ

จะตรวจสอบว่าเมธอดโยนข้อยกเว้นได้อย่างไร?

ใช้ assertThrows(Class, Executable) — มันรับประเภทข้อยกเว้นที่คาดหวังและแลมบ์ดาพร้อมการเรียกเมธอด JUnit ตรวจสอบว่าข้อยกเว้นถูกโยนจริงและส่งคืนเพื่อการตรวจสอบเพิ่มเติม

สรุป

  • JUnit เป็นเฟรมเวิร์กการทดสอบหน่วยมาตรฐานสำหรับ Java และ Kotlin ซึ่งเป็นรากฐานของระบบนิเวศ xUnit
  • คำอธิบายประกอบ @Test, @BeforeEach, @AfterEach จัดการวงจรชีวิตของคลาสทดสอบ
  • การยืนยัน — assertEquals, assertTrue, assertThrows ตรวจสอบความถูกต้องของผลลัพธ์
  • การทดสอบแบบกำหนดพารามิเตอร์ ด้วย @CsvSource และ @MethodSource ลดการทำซ้ำโค้ด
  • JUnit 5 — สถาปัตยกรรมแบบโมดูลาร์พร้อมแพลตฟอร์ม, API Jupiter และการสนับสนุนส่วนขยาย
  • การรวม Android — JUnit ทำงานบน JVM ผ่าน Test Runner มาตรฐานโดยไม่ต้องใช้โปรแกรมจำลอง
  • Test Runner ค้นหาและเรียกใช้เมธอด @Test โดยอัตโนมัติ รายงานผลลัพธ์

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม