Test Doubles — ano ito, mga uri at aplikasyon

May-akda: IT Sectr Nai-publish: 2026-04-10 Oras ng pagbabasa: 9 min

Test Doubles — ay mga bagay na pamalit na ginagamit sa mga unit test sa halip ng mga tunay na dependencies. Ang terminong ito ay ipinakilala ni Gerard Meszaros sa aklat na “­xUnit Test Patterns” (2007) bilang isang pangkalahatang konsepto para sa Mock, Stub, Fake, Spy at Dummy. Ayon kay Martin Fowler (2024), pinapayagan ng Test Doubles ang paghihiwalay ng sinusubok na bahagi mula sa kapaligiran nito, na ginagawang deterministiko, mabilis at malaya sa mga panlabas na serbisyo ang mga test.

Mga Pangunahing

  • Test Doubles — pangkalahatang termino para sa lahat ng uri ng mga bagay na pamalit sa pagsubok
  • Mock sinusuri ang interaksyon: anong mga metodo ang tinawag at sa anong mga argumento
  • Stub nagbabalik ng mga paunang natukoy na halaga nang hindi sinusuri ang mga tawag
  • Fake — isang pinasimpleng gumaganang implementasyon (halimbawa, in-memory database)
  • Spy nagtatala ng mga tawag para sa susunod na beripikasyon, Dummy pumupuno ng mga parameter

Ano ang Test Doubles?

Test Doubles — ay isang termino mula sa industriya ng sasakyan (stunt double, “double” para sa mga aktor) na dinala sa pag-develop ng software. Kung paanong pinapalitan ng isang stunt double ang isang aktor sa isang delikadong eksena, pinapalitan ng Test Double ang isang tunay na bahagi sa isang test scenario. Ito ay kinakailangan kapag ang tunay na dependency ay hindi available, mabagal, hindi deterministiko, o may mga side effect.

Sinasaklaw ng konsepto ng Test Double ang limang tiyak na uri, bawat isa ay lumulutas ng kaniyang sariling gawain. Ang tipolohiya ni Meszaros ay kanonikal at ginagamit sa lahat ng modernong gabay sa pagsubok. Ang pagkakaiba sa pagitan ng mga uri ay nasa antas ng kontrol at beripikasyon: mula sa simpleng pagpuno ng mga parameter (Dummy) hanggang sa kumpletong pagsusuri ng pagkakasunod-sunod ng mga tawag (Mock).

Bakit kinakailangan ang Test Doubles

Ang pangunahing layunin ng Test Doubles ay paghihiwalay ng sinusubok na modyul. Sa mobile development, ang mga tunay na dependency ay mga API server, database, file system, sensor ng device, mga serbisyo ng system (LocationManager, Camera, Bluetooth). Ang direktang paggamit ng mga bahaging ito ay ginagawang mabagal, marupok at umaasa sa kapaligiran ang mga test. Ayon sa Google Testing Blog (2023), ang maayos na nakahiwalay na mga unit test ay tumatakbo sa loob ng millisecond, at ang mga integration test ay sa mga segundo at minuto.

Limang uri ng Test Doubles

Ang klasipikasyon ni Gerard Meszaros ay may kasamang limang uri ng Test Doubles, na nagkakaiba sa pag-uugali at layunin ng paggamit. Ang pag-unawa sa pagkakaiba sa pagitan ng mga ito ay batayan ng tamang unit testing.

Dummy

Dummy — ay isang bagay na ipinapasa sa sinusubok na metodo, ngunit hindi kailanman ginagamit. Ang Dummy ay kailangan lamang upang matugunan ang lagda ng metodo. Sa Kotlin, ito ay madalas na null, emptyList() o isang bagay na may mga pamalit. Ang Dummy ay hindi dapat maglaman ng anumang lohika — kung ito ay tawagin, ang test ay dapat mabigo.

Fake

Fake — ay isang pinasimple ngunit gumaganang implementasyon ng isang interface. Hindi tulad ng Mock at Stub, ang Fake ay naglalaman ng tunay na lohika ng negosyo, ngunit sa pinasimpleng anyo. Ang klasikong halimbawa — InMemoryUserRepository, na nag-iimbak ng data sa HashMap sa halip ng database. Ang Fake ay ginagamit kapag kailangan subukan ang lohika na umaasa sa estado, ngunit walang overhead ng tunay na imprastraktura.

UriLayuninHalimbawa
DummyPunan ang parameternull, walang laman na bagay
FakeGumaganang pinasimpleng implementasyonInMemoryRepository
StubMagbalik ng nakapirming halagawhen(api.getUser()).thenReturn(user)
SpyTalaan ng mga tawag para sa pagsusuriverify(spy).save(user)
MockSuriin ang interaksyonverify(mock).sendEmail(email)

Stub

Stub ay nagbabalik ng mga paunang natukoy na halaga sa mga tiyak na tawag. Hindi sinusuri ng Stub kung ito ay tinawag — nagbibigay lamang ito ng data. Sa Mockito, ang Stub ay nilikha sa pamamagitan ng when(method).thenReturn(value). Ang Stub ay perpekto para sa pagsubok kapag ang dependency ay kailangang magbalik ng isang tiyak na halaga, ngunit ang mismong katotohanan ng tawag ay hindi mahalaga.

Spy

Spy — ay isang pambalot sa paligid ng isang tunay na bagay na nagtatala ng lahat ng tawag para sa susunod na beripikasyon. Hindi tulad ng Mock, ang Spy ay nagdedelegate ng mga tawag sa tunay na bagay, ngunit pinapayagan ang pagsusuri na nangyari ang mga ito. Sa Mockito, ang Spy ay nilikha sa pamamagitan ng spy(realObject). Ang Spy ay kapaki-pakinabang para sa bahagyang mocking kapag gusto mong gumamit ng isang tunay na bagay ngunit suriin ang ilang mga tawag.

Mock

Mock — ay isang bagay na may mga paunang natukoy na inaasahan sa tawag. Sinusuri ng Mock kung ang mga tiyak na metodo ay tinawag na may mga tiyak na argumento at sa isang tiyak na pagkakasunud-sunod. Hindi tulad ng Stub, ang Mock ay nakatuon sa beripikasyon ng pag-uugali, hindi sa pagbabalik ng data. Ang Mock ay ang pinakamakapangyarihan at pinakamadalas gamitin na uri ng Test Double sa mobile development.

Mock at Stub: mga pangunahing pagkakaiba

Ang pagkakaiba sa pagitan ng Mock at Stub ay madalas na nagdudulot ng kalituhan kahit sa mga may karanasang developer. Ang pangunahing pagkakaiba ay sa layunin: sinusuri ng Stub ang estado (state verification), sinusuri ng Mock ang pag-uugali (behavior verification).

Sinasagot ng Stub ang tanong: “ibinalik ba ng code ang tamang resulta?”. Sinasagot ng Mock ang tanong: “tinawag ba ng code ang tamang mga metodo na may tamang mga argumento?”. Sa mobile development, ang Stub ay ginagamit kapag mahalaga ang resulta (halimbawa, data mula sa repository), at ang Mock kapag mahalaga ang mga side effect (halimbawa, pagpapadala ng email, pagsulat sa database).

kotlin
// Stub: pagsusuri ng estado
every { repository.getUsers() } returns listOf(user)
val result = useCase.getUsers()
assertEquals(1, result.size)

// Mock: pagsusuri ng pag-uugali
every { analytics.logEvent("purchase") } returns Unit
useCase.purchase(item)
verify { analytics.logEvent("purchase") }

Mga halimbawa ng Test Doubles sa Kotlin

Mga praktikal na halimbawa ng lahat ng limang uri ng Test Doubles sa Kotlin gamit ang MockK — ang pinakasikat na library ng mocking para sa mga proyektong Android.

Fake: InMemoryUserRepository

kotlin
class InMemoryUserRepository : UserRepository {
    private val store = mutableMapOf<String, User>()

    override fun save(user: User) {
        store[user.email] = user
    }

    override fun findByEmail(email: String): User? {
        return store[email]
    }
}

Stub + Mock: UseCase test

kotlin
class RegisterUseCaseTest {
    private val api = mockk<AuthApi>()
    private val repo = spyk(InMemoryUserRepository())
    private val useCase = RegisterUseCase(api, repo)

    fun `register user successfully`() = runTest {
        // Stub: nagbabalik ng nakapirming tugon ng API
        coEvery { api.register("test@test.com") } returns AuthResult.Success("token123")

        val result = useCase.execute("test@test.com")

        // Verify: sinusuri na ang user ay nai-save
        verify { repo.save(any()) }
        assertTrue(result.isSuccess())
    }
}

Dummy: test na may hindi ginagamit na parameter

kotlin
data class Logger(val appContext: Context, val format: FormatType)

fun `test logger with dummy context`() {
    // Dummy: Ang Context ay hindi ginagamit sa loob ng Logger
    val dummyContext = mockk<Context>()
    val logger = Logger(dummyContext, FormatType.JSON)
    assertEquals(FormatType.JSON, logger.format)
}

Kailan gagamitin ang bawat uri sa mobile development

Ang pagpili ng uri ng Test Double ay depende sa kung ano ang eksaktong sinusubukan: estado, pag-uugali o integrasyon. Sa mobile development sa Android at iOS, ang mga sumusunod na rekomendasyon ay nabuo.

Para sa ViewModel at UseCase

Sa pagsubok ng ViewModel, gumamit ng Mock para sa mga dependency na gumagawa ng mga side effect (mga repository, analytics, nabigasyon) at Stub para sa mga dependency na nagbabalik ng data (mga kliyente ng API, ContentProvider). Ito ay nagpapahintulot na suriin kung tama ang paghawak ng ViewModel sa parehong matagumpay at error na mga senaryo.

Para sa Repository at Layer ng Data

Sa antas ng Repository, mas gusto ang Fake (mga implementasyon ng database na in-memory) at Stub (mga nakapirming tugon ng API). Pinapahintulutan ng Fake ang pagsubok ng lohika ng caching at offline na mode nang walang konfigurasyon ng SQLite. Ginagaya ng Stub ang iba't ibang HTTP status: 200, 404, 500, timeout.

  • Mga unit test ng lohika ng negosyo — Mock para sa lahat ng panlabas na dependency, Dummy para sa hindi ginagamit na mga parameter
  • Mga integration test — Fake sa halip ng Mock (susuriin na gumagana nang sama-sama ang mga bahagi)
  • Mga UI test — Stub para sa mga tugon ng API (sa pamamagitan ng MockWebServer o WireMock)
  • Mga test ng caching — Fake para sa database (in-memory sa halip ng Room/SQLite)
  • Mga test ng asinkrono — Mock na may suporta sa coroutine (MockK + Turbine para sa Flow)

Mga karaniwang pagkakamali sa paggamit ng mga pamalit

Ang hindi tamang paggamit ng Test Doubles — isa sa mga pinakakaraniwang sanhi ng marupok na mga test na nasisira sa bawat refactoring.

Over-mocking: labis na paggamit ng Mock

Ang pinakakaraniwang pagkakamali — ang pag-mock ng lahat. Kung ang bawat dependency sa isang test ay pinalitan ng Mock, ang test ay hihinto sa pagsusuri ng tunay na pag-uugali. Ang Mock ay dapat lamang para sa panlabas na mga dependency (network, database, file system, mga serbisyo ng system). Ang mga panloob na bahagi ng aplikasyon (Value Object, data class, mga simpleng utility) ay hindi dapat palitan.

Under-specification: hindi sapat na espesipikasyon

Ang pangalawang pagkakamali — paglikha ng Mock nang hindi tinutukoy ang mga inaasahan. Kung ang isang metodo ay tinawag nang walang every / when, ang Mock ay nagbabalik ng default na halaga (null, 0, false). Ito ay maaaring humantong sa maling positibong mga test kapag ang Mock ay tahimik na nagbabalik ng null, at ang test ay nagbibigay-kahulugan dito bilang tamang pag-uugali.

Over-verification: labis na beripikasyon

Ang pangatlong pagkakamali — pagsusuri ng bawat tawag ng bawat Mock. Verify ay dapat gamitin lamang para sa mga tawag na kritikal mula sa pananaw ng lohika ng negosyo. Ang labis na beripikasyon ay ginagawang marupok ang mga test: ang pagbabago sa pagkakasunud-sunod ng mga tawag sa production code ay sumisira ng mga test nang hindi binabago ang pag-uugali.

Mga Madalas Itanong

Ano ang pagkakaiba ng Mock at Stub?

Stub ay nagbabalik ng data at sinusuri ang estado (kung ano ang ibinalik), habang Mock ay sinusuri ang pag-uugali (anong mga metodo ang tinawag). Stub = “ibalik ang X”, Mock = “suriin na ang Y ay tinawag na may argumentong Z”. Sa tunay na mga test, ang isang bagay ay madalas na gumaganap bilang parehong Stub at Mock nang sabay.

Kailan gagamitin ang Fake sa halip ng Mock?

Fake ay mas gusto kaysa Mock kapag sinusuri ang lohika na umaasa sa estado: caching, offline mode, mga transaksyon. Ang Fake (in-memory implementasyon) ay nagpapahintulot sa pagsubok ng mga senaryong ito nang walang marupok na mga tawag sa verify. Ang Mock ay mas angkop para sa pagsusuri ng pagpapadala ng data: analytics, push notification, email.

Aling library ng Test Doubles ang mas mahusay para sa Android?

Para sa mga proyektong Android sa Kotlin, inirerekomenda ang MockK. Sinusuportahan nito ang mga coroutine, suspend function, sealed class at extension function nang walang karagdagang konfigurasyon. Para sa mga proyektong Java, ang pamantayan ay nananatiling Mockito — ang pinakasikat na library na may malawak na dokumentasyon.

Paano subukan ang Kotlin Flow gamit ang Test Doubles?

Para sa pagsubok ng Kotlin Flow, gamitin ang library na Turbine kasabay ng MockK. Pinapasimple ng Turbine ang pagsusuri ng emisyon ng Flow: maaari mong suriin ang pagkakasunud-sunod ng mga halaga, pagkumpleto ng daloy at mga eksepsiyon. Ang Stub para sa Flow ay nagbabalik ng flowOf(value), sinusuri ng Mock kung ang Flow ay nakolekta.

Pinapayagan ba ang paggamit ng Test Doubles sa mga UI test?

Oo, ngunit sa antas ng mga tugon ng API, hindi ng mga bahagi ng UI. Ang mga library na MockWebServer (OkHttp) at WireMock ay nagpapahintulot sa pagpapalit ng mga tugon ng HTTP sa mga UI test. Ang mga bahagi ng UI mismo (Compose, SwiftUI Views) ay hindi dapat palitan — ang kanilang pag-uugali ay sinusuri sa pamamagitan ng mga screenshot test at Espresso.

Buod

  • Test Doubles — pangkalahatang termino para sa limang uri ng mga bagay na pamalit: Mock, Stub, Fake, Spy, Dummy
  • Mock sinusuri ang pag-uugali (verify), Stub nagbabalik ng data (thenReturn), Fake — gumagana tulad ng isang pinasimpleng tunay na implementasyon
  • Spy bumabalot sa tunay na bagay at nagtatala ng mga tawag, Dummy pumupuno ng hindi ginagamit na mga parameter
  • Tipolohiya ni Gerard Meszaros — kanonikal na klasipikasyon na ginagamit sa lahat ng modernong framework ng mocking
  • Para sa mga proyektong Kotlin inirerekomenda ang MockK, para sa Java — Mockito, para sa iOS — Cuckoo o OHHTTPStubs
  • Mga karaniwang pagkakamali: over-mocking (pagpapalit ng lahat), under-specification (hindi natukoy na mga inaasahan), over-verification (labis na beripikasyon)
  • Fake ay mas gusto kaysa Mock sa pagsubok ng lohika na may estado — caching, offline mode at mga transaksyon

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din