Mockito — มันคืออะไร แนวคิดสำคัญ และหลักการทำงาน

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

Mockito เป็นเฟรมเวิร์กโอเพนซอร์สสำหรับสร้างวัตถุ mock ในการทดสอบหน่วยของ Java และ Kotlin ซึ่งช่วยให้โค้ดที่กำลังทดสอบสามารถแยกออกจากการพึ่งพาภายนอกได้ ด้วยความช่วยเหลือนี้ นักพัฒนาจะแทนที่พื้นที่เก็บจริง, ไคลเอนต์ API และฐานข้อมูลด้วย stubs ที่ควบคุมได้โดยมีพฤติกรรมที่กำหนดไว้ล่วงหน้า ตาม Mockito.org, ไลบรารีถูกใช้ในมากกว่า 60% ของโปรเจค Java ที่ใช้การทดสอบหน่วย

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

  • Mockito — ไลบรารีสำหรับสร้างวัตถุ mock ที่แทนที่การพึ่งพาจริงในการทดสอบ
  • Mock — วัตถุ stub ที่จำลองพฤติกรรมขององค์ประกอบจริง
  • Stubbing — การกำหนดค่าที่จะส่งคืนเมื่อเรียกเมธอดของ mock
  • Verify — การตรวจสอบว่าเมธอดถูกเรียกด้วยอาร์กิวเมนต์เฉพาะเจาะจง
  • @InjectMocks — การฉีดการพึ่งพา mock โดยอัตโนมัติเข้าไปในวัตถุที่กำลังทดสอบ

Mockito คืออะไร?

Mockito เป็นไลบรารีโอเพนซอร์สสำหรับสร้างวัตถุ mock (stub) ในการทดสอบหน่วยสำหรับ Java, Kotlin และภาษ JVM อื่นๆ ต่างจาก JUnit ที่รับผิดชอบการดำเนินการทดสอบ Mockito แก้ปัญหาการ แยกแยะ — มันแทนที่การพึ่งพาจริงของคลาสที่กำลังทดสอบด้วยวัตถุที่สามารถทำนายได้ล่วงหน้า

หากไม่มี mock, การทดสอบเมธอดที่เข้าถึงฐานข้อมูลหรือ API ภายนอกต้องตั้งค่าสภาพแวดล้อมจริง — การเผยแพร่ฐานข้อมูล, การเริ่มเซิร์ฟเวอร์ Mockito แทนที่การพึ่งพาเหล่านี้ด้วยวัตถุที่มีพฤติกรรมตามที่กำหนด: เมธอด repository.findById(1) จะส่งคืนวัตถุ User ที่กำหนดไว้เสมอโดยไม่ต้องเข้าถึงฐานข้อมูล

สถาปัตยกรรมของ Mockito ขึ้นอยู่กับรูปแบบ Proxy (สำหรับอินเทอร์เฟซและคลาส) ไลบรารีจะสร้างคลาสย่อยหรือพร็อกซีสำหรับประเภทที่ระบุและสกัดกั้นการเรียกเมธอดทั้งหมด, ส่งคืนค่าเริ่มต้นหรือค่าที่กำหนดผ่าน when().thenReturn()

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

หลักการทำงานของ Mockito สร้างขึ้นจากการดำเนินการพื้นฐานสามอย่าง: การสร้าง mock, การกำหนดพฤติกรรม (stubbing) และการตรวจสอบการเรียก (verification) แต่ละการดำเนินการใช้เมธอดสแตติกจากคลาส org.mockito.Mockito — คลาสที่ถูกดาวน์โหลดมากที่สุดในระบบนิเวศของ Java ตามสถิติของ Maven Central การเรียกเมธอดของ mock ทั้งหมดจะถูกบันทึกไว้ในหน่วยความจำ, ซึ่งช่วยให้สามารถตรวจสอบภายหลังผ่าน verify

สามขั้นตอนของการทดสอบกับ Mockito

การทดสอบทั่วไปกับ Mockito ประกอบด้วยสามเฟส: Arrange — การสร้าง mocks และการกำหนด stubs ผ่าน when().thenReturn(), Act — การเรียกเมธอดที่กำลังทดสอบ, Assert — การตรวจสอบผลลัพธ์ผ่าน assertEquals และ verify(mock) วิธีการนี้เรียกว่า AAA (Arrange-Act-Assert)

ตัวอย่างพื้นฐานกับ mock ของ repository

ลองดูการทดสอบง่ายๆ ที่ Mockito แทนที่ repository ของผู้ใช้ เมธอด when().thenReturn() จะกำหนดค่า mock ให้การเรียก findById ส่งคืนวัตถุ User ที่เตรียมไว้ล่วงหน้า

java
// สร้าง mock ของ repository
UserRepository mockRepo = mock(UserRepository.class);

// กำหนดพฤติกรรม: findById(1) ส่งคืนผู้ใช้
when(mockRepo.findById(1)).thenReturn(new User("Alice"));

// ตรวจสอบว่าเมธอดถูกเรียกจริง
User result = mockRepo.findById(1);
assertEquals("Alice", result.getName());
verify(mockRepo).findById(1);

การสร้างวัตถุ mock

Mockito มีสองวิธีในการสร้าง mocks: เมธอดสแตติก mock(Class) และแอนโนเทชั่น @Mock กับการเริ่มต้นผ่าน MockitoAnnotations.openMocks() วิธีแรกกะทัดรัดสำหรับหนึ่งหรือสอง mocks, วิธีที่สองสะดวกเมื่อมีการพึ่งพาจำนวนมาก — แอนโนเทชั่นช่วยลดโค้ด boilerplate

ผ่านเมธอดสแตติก mock()

เมธอด mock() รับคลาสและส่งคืนวัตถุ stub ที่สามารถกำหนดค่าผ่าน when().thenReturn() เมธอดที่ไม่ได้กำหนดค่าทั้งหมดจะส่งคืนค่าเริ่มต้น: 0 สำหรับตัวเลข, false สำหรับ boolean, null สำหรับวัตถุ

java
ApiClient apiClient = mock(ApiClient.class);
Database database = mock(Database.class);

ผ่านแอนโนเทชั่น @Mock กับ JUnit 5

แอนโนเทชั่น @Mock ร่วมกับ @ExtendWith(MockitoExtension.class) จะสร้าง mocks โดยอัตโนมัติสำหรับทุกๆ ฟิลด์ของคลาสทดสอบ MockitoExtension มีหน้าที่รับผิดชอบการเริ่มต้นก่อนแต่ละการทดสอบ

java
@ExtendWith(MockitoExtension.class)
class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    void getUserShouldReturnUserFromRepo() {
        when(userRepository.findById(1)).thenReturn(new User("Alice"));
        User result = userService.getUser(1);
        assertEquals("Alice", result.getName());
    }
}

Stubbing: การกำหนดพฤติกรรมของ mock

Stubbing คือกระบวนการกำหนดว่าเมธอดของ mock ควรจะส่งคืนอะไรเมื่อถูกเรียกด้วยอาร์กิวเมนต์เฉพาะเจาะจง ไวยากรณ์พื้นฐาน: when(mock.method(args)).thenReturn(value) สำหรับสถานการณ์ต่างๆ, Mockito มีตัวแปรเมธอด then หลายแบบ

เมธอดวัตถุประสงค์
thenReturn(value)ส่งคืนค่าที่ระบุเสมอ
thenThrow(exception)เหตุข้อยกเว้นเมื่อเรียก
thenAnswer(answer)คำนวณค่าที่ส่งคืนแบบไดนามิก
thenCallRealMethod()เรียกเมธอดจริง (mock บางส่วน)

การตอบสนองแบบไดนามิกผ่าน thenAnswer

เมื่อค่าที่ส่งคืนขึ้นอยู่กับอาร์กิวเมนต์ของการเรียก, จะใช้ thenAnswer กับ lambda ซึ่งมีประโยชน์ในการจำลองการทำงานกับข้อมูลจริง — ตัวอย่างเช่น, การสร้าง ID โดยอิงตามวัตถุที่ส่งมา

java
when(repository.save(any())).thenAnswer(invocation -> {
    User user = invocation.getArgument(0);
    user.setId(42);
    return user;
});

Verify: การตรวจสอบการโต้ตอบกับ mock

Verify เป็นคุณสมบัติพิเศษของ Mockito ที่ไลบรารีวัตถุ mock รุ่นเก่าๆ (EasyMock, jMock) ไม่มี

Verify ทำให้การทดสอบน่าเชื่อถือมากขึ้นเพราะมันตรวจสอบไม่เฉพาะค่าที่ส่งคืนแต่รวมถึงผลกระทบข้างเคียง — การเรียกเมธอดที่ไม่ส่งคืนผลลัพธ์ (เมธอด void) เมธอด verify(mock).methodName(args) ตรวจสอบว่าเมธอดเฉพาะของ mock ถูกเรียกด้วยอาร์กิวเมนต์ที่ระบุหรือไม่ ซึ่งช่วยให้สามารถทดสอบไม่เฉพาะผลลัพธ์แต่รวมถึงกระบวนการ — ข้อเท็จจริงของการเข้าถึงการพึ่งพา

การตรวจสอบจำนวนการเรียก

โดยค่าเริ่มต้น, verify ตรวจสอบว่าเมธอดถูกเรียกครั้งเดียวพอดี หากต้องการจำนวนที่แตกต่าง, จะใช้ times(n), atLeast(n), never() และตัวแก้ไขอื่นๆ จากคลาส Mockito

java
// ตรวจสอบจำนวนการเรียก
verify(repository, times(3)).save(any());
verify(repository, never()).delete(any());
verify(repository, atLeastOnce()).findById(1);

// ตรวจสอบลำดับการเรียก
InOrder inOrder = inOrder(repository);
inOrder.verify(repository).save(any());
inOrder.verify(repository).flush();

ArgumentCaptor สำหรับการจับอาร์กิวเมนต์

เมื่อต้องตรวจสอบว่าเมธอดถูกเรียกด้วยวัตถุใด, จะใช้ ArgumentCaptor ซึ่งจับค่าอาร์กิวเมนต์ระหว่างการเรียกและช่วยให้ตรวจสอบฟิลด์ของมันทีละตัว ArgumentCaptor มีประโยชน์โดยเฉพาะเมื่อโค้ดที่กำลังทดสอบสร้างวัตถุภายในและส่งต่อไปให้การพึ่งพา — คุณไม่สามารถตรวจสอบวัตถุนั้นด้วยวิธีอื่น

java
ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class);
verify(repository).save(captor.capture());
assertEquals("Alice", captor.getValue().getName());

แอนโนเทชั่น @Mock และ @InjectMocks

@Mock และ @InjectMocks เป็นสองแอนโนเทชั่นหลักของ Mockito ที่ช่วยลดโค้ด boilerplate ได้อย่างมาก @Mock สร้าง mock สำหรับฟิลด์, และ @InjectMocks ฉีด mocks ทั้งหมดจากคลาสทดสอบเข้าไปในวัตถุที่กำลังทดสอบผ่านคอนสตรักเตอร์, setter หรือฟิลด์

กลไกของ @InjectMocks จะพยายามฉีดการพึ่งพาตามลำดับดังนี้: คอนสตรักเตอร์ที่มีจำนวนอาร์กิวเมนต์มากที่สุด, setter ตามประเภท, ฟิลด์ส่วนตัว หากไม่มีวิธีใดทำงานได้, วัตถุจะเหลือการพึ่งพาเป็น null และการทดสอบจะล้มเหลวด้วย NullPointerException

กฎของการใช้ @InjectMocks

สิ่งสำคัญที่ต้องเข้าใจ: @InjectMocks ไม่ได้วิเคราะห์ประเภทของฟิลด์ — มันจะแทนที่ mock ใดก็ตามที่เข้ากันได้ตามประเภท หากคลาสมีสองฟิลด์ที่ประเภทเดียวกัน, Mockito อาจฉีด mock ผิด ในกรณีเช่นนี้, แนะนำให้ใช้คอนสตรักเตอร์ที่ชัดเจนกับพารามิเตอร์ mock

Mockito ในโปรเจค Android

ในการพัฒนา Android, Mockito ถูกใช้ร่วมกับ JUnit เพื่อทดสอบ ViewModel, Repository และ UseCase เนื่องจากคลาสเหล่านี้ทำงานบน JVM โดยไม่มีบริบท Android, Mockito จะแทนที่การพึ่งพาของพวกเขา — Room DAO, Retrofit API, SharedPreferences — ด้วย stubs ที่มีพฤติกรรมที่สามารถทำนายได้ล่วงหน้า

การตั้งค่า Gradle สำหรับ Mockito

เพื่อเพิ่ม Mockito ในโปรเจค Android, เพียงเพิ่มการพึ่งพา mockito-core หรือ mockito-inline (แบบหลังรองรับการทำ mock คลาส final และเมธอดสแตติก) รุ่น 5.12.0 (2024) รวมถึงการสนับสนุน Java 21 และการผนวกรวม JUnit 5 ที่ดีขึ้น

kotlin
// build.gradle.kts (module)
dependencies {
    testImplementation("org.mockito:mockito-core:5.12.0")
    testImplementation("org.mockito:mockito-junit-jupiter:5.12.0")
}

Mockito และ PowerMock: แนวปฏิบัติที่ล้าสมัย

ก่อนหน้านี้, การทำ mock เมธอดสแตติกและคอนสตรักเตอร์จำเป็นต้องใช้ PowerMock — ส่วนขยายที่ทำงานผ่านการเปลี่ยนแปลงไฟล์โค้ด ตั้งแต่ Mockito 5.x กับ mockito-inline, ความสามารถนี้ถูกรวมอยู่ในตัวโดยตรง: mockStatic(ClassName.class) ช่วยให้สามารถทำ mock เมธอดสแตติกได้โดยไม่ต้องใช้ไลบรารีเพิ่มเติม

การทดสอบ ViewModel กับ Mockito

สถานการณ์ทั่วไป: ViewModel เรียกเมธอดของ repository และแปลงผลลัพธ์เป็นสถานะ UI Mockito แทนที่ repository, และการทดสอบจะตรวจสอบว่า ViewModel จัดการกับการตอบสนองที่สำเร็จและข้อผิดพลาดได้อย่างถูกต้อง เมื่อใช้ Clean Architecture, mocks จะถูกสร้างขึ้นสำหรับแต่ละชั้น: DataSource, Repository และ UseCase — ซึ่งช่วยให้สามารถทดสอบแต่ละชั้นได้อย่างโดดเดี่ยว

  • กรณีสำเร็จ — when(repo.getData()).thenReturn(Result.success(data)) → ตรวจสอบ state = Success(data).
  • กรณีข้อผิดพลาด — when(repo.getData()).thenReturn(Result.error(exception)) → ตรวจสอบ state = Error(message).
  • สถานะการโหลด — verify ว่า ViewModel ได้ตั้งค่า isLoading = true ก่อนเรียก repository

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

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

Mockito เป็นไลบรารีสำหรับ Java และ Kotlin ที่ใช้ proxy และ reflection MockK เป็นไลบรารี Kotlin-first ที่รองรับ coroutines, ฟังก์ชันส่วนขยาย และคลาส final โดยไม่ต้องกำหนดค่าเพิ่มเติม

จะสร้าง mock สำหรับคลาส final ใน Mockito ได้อย่างไร?

ตั้งแต่ Mockito 2.1, การทำ mock คลาส final รองรับผ่าน opt-in ในรุ่น 5.x (mockito-inline), นี้เปิดใช้โดยค่าเริ่มต้น เพียงเพิ่มการพึ่งพา mockito-inline และใช้เมธอด mock() มาตรฐาน

Spy ใน Mockito คืออะไร?

Spy คือ mock บางส่วนที่โดยค่าเริ่มต้นจะเรียกเมธอดจริงแต่อนุญาตให้เขียนทับบางส่วนผ่าน when().thenReturn() Spy มีประโยชน์สำหรับการทดสอบโค้ด legacy เมื่อไม่สามารถเขียนคลาสใหม่ทั้งหมดได้

ความแตกต่างระหว่าง thenReturn และ thenAnswer คืออะไร?

thenReturn จะส่งคืนค่าเดียวกันเสมอ, โดยไม่ขึ้นอยู่กับอาร์กิวเมนต์ thenAnswer คำนวณค่าที่ส่งคืนโดยอิงตามการเรียกใช้ — อาร์กิวเมนต์, ตัว mock เอง และสถานะ สำหรับการตอบสนองแบบไดนามิก, ให้ใช้ thenAnswer เสมอ

ทำไม verify ถึงสำคัญสำหรับการทดสอบกับ mocks?

Verify ตรวจสอบไม่เฉพาะผลลัพธ์แต่รวมถึงกระบวนการ — ข้อเท็จจริงของการเข้าถึงการพึ่งพา ซึ่งมีความสำคัญสำหรับบริการที่ต้องบันทึกข้อมูลหรือส่งการแจ้งเตือน หากไม่มี verify, การทดสอบจะไม่ตรวจพบว่าเมธอดไม่ได้เรียก save() หรือ send()

สรุป

  • Mockito — ไลบรารีสำหรับสร้างวัตถุ mock, มาตรฐานของจริงสำหรับการทำ mock ใน Java และ Kotlin
  • Mocks ถูกสร้างผ่าน mock(Class) หรือแอนโนเทชั่น @Mock กับ MockitoExtension
  • Stubbing ผ่าน when().thenReturn() กำหนดพฤติกรรมของเมธอด mock
  • Verify ตรวจสอบข้อเท็จจริงและจำนวนการเรียกเมธอด mock ด้วยอาร์กิวเมนต์ที่ระบุ
  • @InjectMocks ฉีด mocks โดยอัตโนมัติเข้าไปในวัตถุที่กำลังทดสอบ
  • การผนวกรวม Android — Mockito ใช้ในการทดสอบ ViewModel, Repository และ UseCase
  • ArgumentCaptor จับอาร์กิวเมนต์ของการเรียกเพื่อการตรวจสอบรายละเอียดของฟิลด์วัตถุ

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

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

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

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