Fake — ano ito, layunin at kung paano gamitin sa pagsubok

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

Fake (peyk) — isang gumaganang pinasimpleng implementasyon ng dependency na kumikilos tulad ng isang tunay na component, ngunit gumagamit ng in-memory storage o iba pang magaan na mekanismo sa halip na production infrastructure. Hindi tulad ng stub, ang fake ay naglalaman ng tunay na business logic — pag-uuri, pag-filter, pag-aggregate — basta walang panlabas na epekto. In-memory database sa halip na Room o HashMap sa halip na SharedPreferences — mga klasikong halimbawa. Higit pa sa klasipikasyon ng test doubles ni Martin Fowler.

Mga Pangunahing Punto

  • Fake — pinasimpleng gumaganang implementasyon na may tunay na lohika, ngunit walang panlabas na dependency
  • In-memory storage — fake-repository ay nag-iimbak ng data sa HashMap, hindi sa database
  • Pagkakaiba sa Stub — stub ay nagbabalik ng nakapirming data, ang fake ay naglalaman ng executable na lohika
  • Android — InMemoryUserRepository bilang Fake para sa pagsubok ng ViewModel at UseCase
  • iOS — FakeNetworkSession na may URLProtocol at test data sa halip na tunay na server

Ano ang Fake at bakit kailangan ito sa pagsubok?

Fake — isang kumpleto ngunit magaan na implementasyon ng isang interface, angkop para sa pagsubok. Ang termino ay ipinakilala ni Gerard Meszaros (2007) sa aklat na «xUnit Test Patterns». Hindi tulad ng stub na nagbabalik ng mahigpit na paunang natukoy na mga sagot, ang fake ay naglalaman ng executable code: maaari itong mag-uri ng listahan, mag-filter ayon sa kondisyon, magbilang ng mga record. Ang tanging pagkakaiba mula sa production implementasyon — ang fake ay gumagawa gamit ang in-memory data at hindi nagsasagawa ng tunay na I/O operations.

Pangunahing bentahe — bilis. Ang mga pagsubok na may fake ay isinasagawa sa millisecond, dahil walang access sa disk, network, o database. Ang in-memory HashMap ay gumagana nang 100-1000 beses na mas mabilis kaysa Room o CoreData. Kasabay nito, sinusuri ng fake ang tunay na business logic: pag-uuri, pag-filter, pag-aggregate — lahat ng hindi maaaring suriin ng stub, dahil ang stub ay nagbabalik lamang ng sinabi dito. Ang fake ay nagbibigay ng kumpiyansa na ang code ay wastong nagproseso ng data, hindi lamang tumatanggap ng paunang natukoy na sagot.

Kailan mas gusto ang Fake kaysa Stub

Mas gusto ang Fake kaysa Stub — kung ang component na sinusuri ay nagsasagawa ng maraming operasyon sa data (kinuha, na-filter, na-uri, na-save), ang stub ay mangangailangan ng configuration ng bawat tawag nang hiwalay. Ang fake ay naglalaman ng lohika sa loob — ang pagsubok ay tumatawag lamang ng mga pamamaraan at sinusuri ang resulta. Sa IT Sectr ginagamit namin ang fake para sa lahat ng repository sa unit tests: ang fake-repository na may HashMap ay sumasaklaw sa 90% ng mga senaryo nang walang configuration ng Mockito o MockK.

Fake vs Stub vs Mock: kailan pipiliin ang alin

Pamantayan sa pagpili — tukuyin kung ano ang sinusuri ng pagsubok: estado o interaksyon. Kung sinusuri ng pagsubok ang estado (resulta ng trabaho) at gumagamit ng lohika — kailangan ang fake. Kung ang pagsubok ay nangangailangan lamang ng input data nang walang lohika — sapat na ang stub. Kung sinusuri ng pagsubok ang katotohanan ng pagtawag ng pamamaraan — kailangan ang mock. Ang paghahalo ng mga uri ng test doubles sa isang pagsubok ay nagpapahirap sa pag-unawa at nagpapataas ng hina.

PamantayanFakeStubMock
Pagkakaroon ng lohikaOo (pinasimple)HindiHindi
BilisMataasPinakamataasMataas
Pagsusuri ng pag-uugaliHindi direktaHindiOo (verify)
PagpapanatiliIsang klase bawat interfaceConfiguration bawat pagsubokConfiguration bawat pagsubok
RealismoMataas (gumagana ang code)Mababa (nakapirming data)Katamtaman
Panganib ng false positiveMababaKatamtamanMataas (marupok na pagsubok)

Anti-pattern: Fake na hindi fake — isang karaniwang pagkakamali kapag tinawag ng developer na fake ang isang bagay na sa totoo ay stub o mock. Kung ang iyong InMemoryUserRepository ay hindi naglalaman ng lohika (pag-filter, pag-uuri) — ito ay hindi fake, kundi stub na may in-memory storage. Ang fake ay naiiba sa stub dahil sa pagkakaroon ng executable na lohika. Kung ang fake-repository ay nagbabalik lamang ng inilagay dito at hindi nagproseso ng data — gumamit ng mock o stub.

Praktikal na panuntunan sa pagpili ng test double

Praktikal na rekomendasyon — magsimula sa fake para sa bawat repository o serbisyo. Kung ang fake ay mas kumplikado kaysa 50 linya — hatiin sa maraming klase. Kung ang fake ay hindi talaga kailangan (ang pagsubok ay sumusuri lamang ng isang senaryo na may nakapirming data) — gumamit ng stub. Kung sinusuri ng pagsubok kung ang isang pamamaraan ay tinawag na may tiyak na mga parameter — gumamit ng mock. Huwag i-optimize ang pagpili nang maaga: sumulat ng fake, at kung ito ay naging kalabisan, palitan ito ng stub sa partikular na pagsubok.

Paggawa ng Fake-objects sa Android para sa Room at Retrofit

Fake-repository para sa Room — tipikal na halimbawa ng fake sa Android. Ang production implementasyon ng UserRepository ay gumagamit ng Room DAO na may SQLite queries. Ang fake na bersyon ay nag-iimbak ng data sa MutableList o HashMap at nagpapatupad ng parehong mga pamamaraan: getUser(id), saveUser(user), deleteUser(id). Ang fake ay naglalaman ng lohika ng paghahanap, pag-filter at pag-uuri — pareho sa production repository, ngunit walang SQL. Ito ay nagbibigay-daan sa pagsubok ng ViewModel at UseCase nang walang configuration ng Room database.

kotlin
class FakeUserRepository : UserRepository {

    private val users = mutableListOf<User>()

    override suspend fun getUser(id: String): User? {
        return users.find { it.id == id }
    }

    override suspend fun saveUser(user: User) {
        val index = users.indexOfFirst { it.id == user.id }
        if (index >= 0) users[index] = user
        else users.add(user)
    }

    override suspend fun search(query: String): List<User> {
        return users.filter {
            it.name.contains(query, ignoreCase = true)
        }
    }
}

Fake para sa Retrofit API — sa halip na MockWebServer (na stub, hindi fake) maaaring gumawa ng implementasyon ng ApiService na nagbabalik ng data mula sa in-memory collection. Pagkakaiba: ang MockWebServer ay humarang sa HTTP at nagbabalik ng JSON, habang ang fake-ApiService ay gumagana sa antas ng Kotlin interface nang walang serialization. Ang fake ay mas mabilis (walang JSON parsing) at mas simple i-debug (gumagana sa parehong proseso, naka-type). Angkop para sa mga pagsubok kung saan hindi mahalaga ang HTTP semantics (status code, headers).

FakeSharedPreferences para sa mabilis na pagsubok

— isa pang karaniwang senaryo. Ang production SharedPreferences ay nagsusulat sa disk sa pamamagitan ng commit/apply. Ang fake na bersyon ay nag-iimbak ng key-value pairs sa HashMap at agad na nagbabalik ng data. Sinusuportahan ang parehong mga pamamaraan: getString, putString, getInt, putInt, clear. Para sa Jetpack DataStore ang analog ay FakeDataStore na may in-memory storage. Ang ganitong mga fake ay nagpapabilis ng pagsubok nang sampu-sampung beses, dahil walang operasyon ng pagsusulat sa disk.

Fake Implementasyon sa iOS na may in-memory storage

Fake sa Swift — binuo sa pamamagitan ng mga protocol. Ang production class ay nagpapatupad ng protocol na may tunay na lohika (CoreData, URLSession). Ang fake structure ay nagpapatupad ng parehong protocol na may in-memory storage at pinasimple na lohika. Ang Swift ay isang wika na may value semantics, kaya ang mga fake structure ay immutable at ligtas sa multi-threaded na pagsubok. Ito ay nagbibigay ng kalamangan kaysa Android analog: ang pag-access sa in-memory data ay hindi kailangang i-synchronize.

swift
protocol UserRepositoryProtocol {
    func getUser(id: String) async -> User?
    func saveUser(user: User) async
}

final class FakeUserRepository: UserRepositoryProtocol {
    private var storage: [String: User] = [:]

    func getUser(id: String) async -> User? {
        return storage[id]
    }

    func saveUser(user: User) async {
        storage[user.id] = user
    }
}

final class UserViewModelTests: XCTestCase {
    func test_save_and_load() async {
        let fake = FakeUserRepository()
        let vm = UserViewModel(repository: fake)
        let user = User(id: "1", name: "Alice")

        await vm.saveUser(user)
        let loaded = await vm.getUser(id: "1")

        XCTAssertEqual(loaded?.name, "Alice")
    }
}

Fake para sa CoreData — sa iOS projects maaaring gumawa ng in-memory NSPersistentContainer sa pamamagitan ng pag-set ng description.type = NSInMemoryStoreType. Ito ay isang buong CoreData stack na gumagana sa memorya. Ang ganitong fake ay nagbibigay-daan sa pagsubok ng NSFetchRequest, predicates at pag-uuri nang hindi gumagawa ng SQLite file. Bilis: ang mga pagsubok sa in-memory CoreData ay isinasagawa nang 5-10 beses na mas mabilis kaysa sa disk analog. Kakulangan: kailangan i-configure ang NSManagedObjectModel sa bawat pagkakataon.

FakeURLProtocol — isang subclass ng URLProtocol para sa pagharang ng network requests sa iOS. Nagrerehistro sa pamamagitan ng URLProtocol.registerClass(fakeProtocol). Sa loob ay naglalaman ng in-memory dictionary URL -> Data at nagbabalik ng data nang walang tunay na request. Pagkakaiba sa stub: ang FakeURLProtocol ay maaaring suriin ang body ng request, headers at magbalik ng iba't ibang response depende sa input data. Ito ay fake dahil naglalaman ito ng request routing logic.

Mga Pattern ng Paggamit ng Fake sa Mobile Projects

Fake bilang Test Fixture — ilipat ang mga fake class sa isang shared test module (androidTest/sharedTest o TestSupport). Lahat ng pagsubok sa project ay gumagamit ng parehong InMemoryUserRepository. Ito ay nag-aalis ng pagdoble ng configuration ng mock objects sa bawat pagsubok at ginagarantiyahan ang pare-parehong pag-uugali. Ang pagbabago ng fake logic ay nag-a-update ng lahat ng pagsubok nang sabay-sabay. Sa IT Sectr, iniimbak namin ang mga fake class sa sharedTest/java/com/itSectr/fake/ at ikinokonekta sa pamamagitan ng implementation project(:sharedTest).

Fake na may paunang itinakdang data — madalas ang mga pagsubok ay nangangailangan ng repository na naglalaman na ng ilang record. Solusyon: factory method na fakeWithData(vararg items) o built-in na method na addDefaultData(). Ang factory ay lumikha ng fake, pinupuno ito ng tipikal na data at nagbabalik ng object na handa nang gamitin. Ito ay nagbabawas ng boilerplate sa mga pagsubok: sa halip na i-configure ang mga mock call, ang pagsubok ay tumatawag lamang ng FakeUserRepository.withUsers(alice, bob).

Fake na may pagbibilang ng tawag — minsan kailangan suriin hindi lamang ang estado, kundi pati ang bilang ng mga tawag. Ang fake ay maaaring maglaman ng mga counter: saveCallCount, getUserCallCount. Sinusuri ng pagsubok ang counter pagkatapos ng execution. Ito ay isang kompromiso sa pagitan ng purong fake (pagsusuri ng estado) at mock (pagsusuri ng interaksyon). Ang mga counter ay hindi sumusuri ng mga argumento at pagkakasunud-sunod ng tawag — bilang lamang. Para sa pagsusuri ng argumento gumamit ng mock.

Fake na may Callback — para sa pagsubok ng asynchronous na senaryo, ang fake ay maaaring tumanggap ng callback sa bawat tawag: beforeGetUser, afterSaveUser. Ito ay nagbibigay-daan sa pag-simulate ng pagkaantala, error o pagsusuri ng intermediate na estado. Ang ganitong approach ay kapaki-pakinabang para sa pagsubok ng UI loading states: ang fake ay huminto nang 100 ms, at sinusuri ng pagsubok kung ang screen ay nagpapakita ng loader. Sa production, ang callback ay wala — ito ay purong testing functionality.

Mga Madalas Itanong

Ano ang pagkakaiba ng Fake at Stub?

Fake ay naglalaman ng gumaganang lohika — nagfa-filter, nag-uuri, nagbibilang. Ang Stub ay nagbabalik lamang ng paunang natukoy na mga sagot nang walang lohika. Kung ang object ay may branching (if/else, when) — ito ay fake. Kung ito ay naglalaman lamang ng return values — ito ay stub. Ang fake ay mas mahal sa pagpapanatili, ngunit nagbibigay ng mas makatotohanang pagsubok.

Kailan maaaring makasama ang fake?

Kapag ang fake logic ay hindi tumutugma sa production logic. Halimbawa, ang FakeUserRepository ay gumagamit ng case-sensitive na paghahanap, habang ang production ay case-insensitive. Ang pagsubok ay pumasa, ngunit sa katotohanan ay may bug. Solusyon: subukan ang fake logic nang hiwalay o gumamit lamang ng fakes para sa mga interface na may simpleng lohika (CRUD operations). Para sa kumplikadong lohika, sumulat ng integration test na may tunay na database.

Ang Fake ba ay pareho ng in-memory database?

In-memory database — isa sa mga variant ng fake. Ang Room.inMemoryDatabaseBuilder() ay lumikha ng in-memory SQLite na kumikilos tulad ng production database. Ito ay isang ganap na fake. Ngunit ang fake ay maaari ding nasa repository level (walang SQL) at network level (FakeApiService). Ang in-memory database ay isang partikular na kaso ng fake kung saan ang lohika ay pinakamalapit sa tunay.

Maaari bang pagsamahin ang Fake at Mock sa isang pagsubok?

Oo, ngunit nang may pag-iingat. Fake para sa repository (data), Mock para sa AnalyticsTracker (beripikasyon ng kaganapan). Paghihiwalay ayon sa layer: fake para sa data layer, mock para sa analytics/logging layer. Huwag gumawa ng isang object na parehong fake at mock — ito ay lumalabag sa Single Responsibility Principle at nakakalito sa pagsubok.

Paano subukan ang Fake mismo?

Subukan ang fake gamit ang parehong pagsubok gaya ng production implementasyon. Kung mayroon kang UserRepositoryTest na sumusuri ng save, get, delete — patakbuhin ito nang dalawang beses: gamit ang FakeUserRepository at gamit ang RealUserRepository. Ginagarantiyahan nito na ang fake ay umuulit ng pag-uugali ng production class. Kung ang fake ay magsimulang kumilos nang iba — ang pagsubok ay mabibigo sa parehong implementasyon.

Buod

  • Fake — gumaganang pinasimpleng implementasyon ng dependency na may tunay na business logic at in-memory storage
  • Pagkakaiba sa Stub — fake ay naglalaman ng lohika (pag-filter, pag-uuri), stub ay nagbabalik lamang ng data
  • Bilis — fake ay gumagana nang 100-1000 beses na mas mabilis kaysa production implementasyon nang walang I/O operations
  • Android — InMemoryUserRepository, FakeDataStore, in-memory Room sa pamamagitan ng Room.inMemoryDatabaseBuilder
  • iOS — protocol-based fake, in-memory CoreData, FakeURLProtocol para sa HTTP interception
  • Pinakamahusay na kasanayan — ilipat ang fake sa shared test module at gamitin sa lahat ng pagsubok ng proyekto
  • Subukan ang fake — patakbuhin ang parehong pagsubok sa fake at production implementasyon para sa pagsusuri ng consistency

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