0Pricing
Android Academy · บทเรียน

การจำลองด้วย Mockito

แยก dependency ด้วย Mockito และ MockK กำหนดค่าผลลัพธ์จำลอง ตรวจสอบการโต้ตอบ ดักจับอาร์กิวเมนต์ และใช้สายลับสำหรับการจำลองบางส่วน

การจำลองด้วย Mockito เป็นบทเรียน Android Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Android Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน

Mocking คืออะไร

mock คือออบเจ็กต์จำลองที่ใช้แทนการพึ่งพาจริงในการทดสอบ ต่างจาก Fake (การนำไปใช้งานในหน่วยความจำที่ทำงานได้จริง) mock จะ:

  • ถูกสร้างโดยอัตโนมัติด้วยไลบรารี
  • บันทึกว่าเรียกเมธอดใดและส่งอาร์กิวเมนต์ใดไป
  • คืนค่าตามที่คุณกำหนด (การกำหนดพฤติกรรมจำลอง)
  • ให้คุณ ตรวจสอบ การโต้ตอบหลังการทดสอบ

การตั้งค่า Mockito

เพิ่ม Mockito และ MockK (ทางเลือกที่ออกแบบมาสำหรับ Kotlin) ลงใน app/build.gradle:

// app/build.gradle:
testImplementation 'org.mockito:mockito-core:5.10.0'
testImplementation 'org.mockito.kotlin:mockito-kotlin:5.2.1'

// MockK (Kotlin-idiomatic alternative to Mockito):
testImplementation 'io.mockk:mockk:1.13.10'

การสร้าง Mock

สร้าง mock ด้วย mock() หรือคำอธิบายประกอบ @Mock:

import org.mockito.kotlin.*

interface UserApi {
    suspend fun fetchUsers(): List<User>
    suspend fun deleteUser(id: Int)
}

class RepositoryTest {

    // Option 1: create inline
    private val api: UserApi = mock()

    // Option 2: use annotation + MockitoJUnit4Runner
    @Mock lateinit var api2: UserApi

    @get:Rule
    val mockitoRule = MockitoJUnit.rule()
}

การกำหนดพฤติกรรมจำลอง — กำหนดค่าที่คืนกลับ

ใช้ whenever(mock.method()).thenReturn(value) เพื่อกำหนดค่าที่ mock จะคืนกลับ:

val api: UserApi = mock()

// Stub a return value:
whenever(api.fetchUsers()).thenReturn(
    listOf(User(1, "Alice"), User(2, "Bob"))
)

// Stub an exception:
whenever(api.fetchUsers()).thenThrow(RuntimeException("Network error"))

// Return different values on consecutive calls:
whenever(api.fetchUsers())
    .thenReturn(emptyList())           // first call
    .thenReturn(listOf(User(1, "Alice"))) // second call

verify() — ตรวจสอบการโต้ตอบ

ใช้ verify() เพื่อตรวจสอบยืนยันว่าเมธอดถูกเรียก และถูกเรียกกี่ครั้ง:

val api: UserApi = mock()
val repo = UserRepository(api)

repo.refreshUsers()

// Verify that fetchUsers() was called exactly once:
verify(api).fetchUsers()

// Verify called with specific argument:
repo.deleteUser(42)
verify(api).deleteUser(42)

// Verify called exactly 3 times:
verify(api, times(3)).fetchUsers()

// Verify never called:
verify(api, never()).deleteUser(any())

ArgumentCaptor

ArgumentCaptor จับอาร์กิวเมนต์ที่ส่งให้เมธอดของ mock เพื่อให้คุณตรวจสอบค่าได้:

val api: UserApi = mock()
val captor = argumentCaptor<User>()

val repo = UserRepository(api)
repo.saveUser(User(1, "Alice"))

verify(api).saveUser(captor.capture())

val captured = captor.firstValue
assertEquals(1, captured.id)
assertEquals("Alice", captured.name)

MockK — การจำลองที่ออกแบบมาสำหรับ Kotlin

MockK ออกแบบมาสำหรับ Kotlin และรองรับฟังก์ชันส่วนขยาย โครูทีน และออบเจ็กต์โดยตรง:

import io.mockk.*

val api = mockk<UserApi>()

// Stub:
every { api.fetchUsers() } returns listOf(User(1, "Alice"))

// Stub suspend function:
coEvery { api.fetchUsers() } returns listOf(User(1, "Alice"))

// Verify:
val repo = UserRepository(api)
runBlocking { repo.refresh() }
coVerify { api.fetchUsers() }

การจำลองโครูทีนด้วย MockK

ใช้ coEvery และ coVerify กับฟังก์ชัน suspend:

val api = mockk<UserApi>()

// Stub suspend function:
coEvery { api.fetchUsers() } returns listOf(User(1, "Alice"))
coEvery { api.deleteUser(any()) } just Runs  // returns Unit

// Test:
runTest {
    val repo = UserRepository(api)
    repo.refresh()
    coVerify(exactly = 1) { api.fetchUsers() }
    coVerify(exactly = 0) { api.deleteUser(any()) }
}

Spy — การจำลองบางส่วน

spy จะครอบออบเจ็กต์จริงไว้ โดยค่าเริ่มต้นจะเรียกเมธอดจริง เว้นแต่จะกำหนดทับ:

// Mockito Spy:
val realList = mutableListOf("a", "b", "c")
val spyList = spy(realList)

// Real method called:
spyList.add("d")
assertEquals(4, spyList.size)   // real add() was called

// Override specific method:
doReturn(99).`when`(spyList).size
assertEquals(99, spyList.size)  // overridden

// MockK Spy:
val spyObj = spyk(RealService())
every { spyObj.expensiveCall() } returns "fake result"

ควรใช้ Mock หรือ Fake เมื่อใด

แนวทางเชิงปฏิบัติ:

  • ใช้ Fake เมื่อต้องการการนำไปใช้งานในหน่วยความจำที่ทำงานได้จริง (DAO, repository) — อ่านง่ายกว่าและไม่ต้องใช้ไลบรารี
  • ใช้ Mock เมื่อต้องตรวจสอบว่าเมธอดหนึ่งถูกเรียกด้วยอาร์กิวเมนต์ที่กำหนด (เหตุการณ์การวิเคราะห์ข้อมูล, การเรียก API)
  • หลีกเลี่ยงการใช้ mock มากเกินไป — หากจำลองทุกอย่าง การทดสอบจะตรวจสอบ mock ไม่ใช่ตรรกะของคุณ

ข้อผิดพลาดที่พบบ่อย

ข้อควรระวังในการใช้ mocking:

  • จำลองออบเจ็กต์ค่า — ควรจำลองอินเทอร์เฟซ/สิ่งนามธรรม ไม่ใช่คลาสข้อมูล
  • จำลองลึกเกินไป — หากต้องใช้ mock 5 ตัวในการทดสอบเดียว โค้ดก็เชื่อมโยงกันแน่นเกินไป
  • ไม่ตรวจสอบ เมื่อการโต้ตอบมีความสำคัญ — อย่ากำหนดพฤติกรรมจำลองอย่างเดียว ต้องตรวจสอบด้วย
  • ค่าเริ่มต้นของ Mockito + Kotlin — พารามิเตอร์ Kotlin ไม่เป็น null โดยค่าเริ่มต้น ให้ใช้ mockito-kotlin หรือ MockK เพื่อหลีกเลี่ยงปัญหา null ที่คาดไม่ถึง

การจำลองออบเจ็กต์และ Companion Object

MockK สามารถจำลองออบเจ็กต์ Kotlin และ companion object ได้ ซึ่ง Mockito ทำไม่ได้:

object DateProvider {
    fun today(): String = "2024-01-01"
}

// In test:
mockkObject(DateProvider)
every { DateProvider.today() } returns "2099-12-31"

val result = DateProvider.today()
assertEquals("2099-12-31", result)

// Restore after test:
unmockkObject(DateProvider)

ตรวจสอบความเข้าใจ

verify() มีจุดประสงค์ใดในการทดสอบด้วย Mockito หรือ MockK

ทบทวน: การจำลองด้วย Mockito และ MockK

Mock ช่วยแยกและตรวจสอบพฤติกรรมได้:

  • mock() / mockk() — สร้าง mock จากอินเทอร์เฟซหรือคลาส
  • whenever(...).thenReturn(...) / every { } returns ... — กำหนดค่าที่คืนกลับ
  • coEvery / coVerify — สำหรับฟังก์ชัน suspend ของ Kotlin (MockK)
  • verify(mock).method(args) — ตรวจสอบว่าเมธอดถูกเรียก
  • ArgumentCaptor — จับและตรวจสอบอาร์กิวเมนต์
  • spy() / spyk() — จำลองออบเจ็กต์จริงบางส่วน
  • ควรใช้ Fake สำหรับข้อมูล และใช้ Mock เพื่อตรวจสอบพฤติกรรม

ถัดไป: การทดสอบ UI ด้วย Espresso

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

บทเรียน “การจำลองด้วย Mockito” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การจำลองด้วย Mockito” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Android Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การจำลองด้วย Mockito”

แยก dependency ด้วย Mockito และ MockK กำหนดค่าผลลัพธ์จำลอง ตรวจสอบการโต้ตอบ ดักจับอาร์กิวเมนต์ และใช้สายลับสำหรับการจำลองบางส่วน คุณปฏิบัติ Android Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Android Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Android Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “การจำลองด้วย Mockito” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Android Academy นี้ได้ไหม

ได้ บทเรียน Android Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การทดสอบหน่วยด้วย JUnit
  2. การจำลองด้วย Mockito
  3. การทดสอบส่วนติดต่อผู้ใช้ด้วย Espresso
  4. การดีบักและการวิเคราะห์ประสิทธิภาพ
← กลับไปที่ Android Academy