Fake — co to je, účel a jak používat v testování

Autor: IT Sectr Publikováno: 2026-04-10 Doba čtení: 9 min

Fake (fejk) — fungující zjednodušená implementace závislosti, která se chová jako skutečná komponenta, ale místo produkční infrastruktury používá in-memory úložiště nebo jiné lehké mechanismy. Na rozdíl od stub, fake obsahuje skutečnou obchodní logiku — řazení, filtrování, agregaci — prostě bez vnějších efektů. In-memory databáze místo Room nebo HashMap místo SharedPreferences — klasické příklady. Více v klasifikaci test doubles Martina Fowlera.

Hlavní body

  • Fake — zjednodušená fungující implementace se skutečnou logikou, ale bez vnějších závislostí
  • In-memory úložiště — fake-repozitář ukládá data v HashMap, ne v databázi
  • Rozdíl od Stub — stub vrací pevná data, fake obsahuje spustitelnou logiku
  • Android — InMemoryUserRepository jako Fake pro testování ViewModel a UseCase
  • iOS — FakeNetworkSession s URLProtocol a testovacími daty místo skutečného serveru

Co je Fake a proč je potřeba v testování?

Fake — úplná, ale lehká implementace rozhraní, vhodná pro testování. Termín zavedl Gerard Meszaros (2007) v knize «xUnit Test Patterns». Na rozdíl od stub, který vrací striktně předdefinované odpovědi, fake obsahuje spustitelný kód: může řadit seznam, filtrovat podle podmínky, počítat záznamy. Jediný rozdíl od produkční implementace — fake pracuje s in-memory daty a neprovádí skutečné I/O operace.

Hlavní výhoda — rychlost. Testy s fake se provádějí v milisekundách, protože není přístup k disku, síti nebo databázi. In-memory HashMap pracuje 100-1000 krát rychleji než Room nebo CoreData. Zároveň fake kontroluje skutečnou obchodní logiku: řazení, filtrování, agregaci — vše, co stub nemůže zkontrolovat, protože stub vrací jen to, co mu bylo řečeno. Fake dává jistotu, že kód správně zpracovává data, nejen přijímá předdefinovanou odpověď.

Kdy je Fake lepší než Stub

Fake je lepší než Stub — pokud testovaná komponenta provádí několik operací s daty (načetl, filtroval, seřadil, uložil), stub bude vyžadovat konfiguraci každého volání zvlášť. Fake obsahuje logiku uvnitř — test jednoduše volá metody a kontroluje výsledek. V IT Sectr používáme fake pro všechny repozitáře v unit testech: fake-repozitář s HashMap pokrývá 90% scénářů bez konfigurace Mockito nebo MockK.

Fake vs Stub vs Mock: kdy co vybrat

Kritérium výběru — určete, co test kontroluje: stav nebo interakci. Pokud test kontroluje stav (výsledek práce) a používá logiku — je potřeba fake. Pokud test potřebuje pouze vstupní data bez logiky — stačí stub. Pokud test kontroluje samotné volání metody — je potřeba mock. Míchání typů test doubles v jednom testu ztěžuje porozumění a zvyšuje křehkost.

KritériumFakeStubMock
Přítomnost logikyAno (zjednodušená)NeNe
RychlostVysokáMaximálníVysoká
Kontrola chováníNepřímáNeAno (verify)
ÚdržbaJedna třída na rozhraníKonfigurace pro každý testKonfigurace pro každý test
RealismusVysoký (kód funguje)Nízký (pevná data)Střední
Riziko falešných poplachůNízkéStředníVysoké (křehké testy)

Antivzor: Fake, který není fake — častá chyba, když vývojář nazývá fake objekt, který je ve skutečnosti stub nebo mock. Pokud váš InMemoryUserRepository neobsahuje logiku (filtrování, řazení) — není to fake, ale stub s in-memory úložištěm. Fake se liší od stub právě přítomností spustitelné logiky. Pokud fake-repozitář pouze vrací to, co do něj bylo vloženo, a nezpracovává data — použijte mock nebo stub.

Praktické pravidlo pro výběr test double

Praktické doporučení — začněte fake pro každý repozitář nebo službu. Pokud je fake složitější než 50 řádků — rozdělte ho do několika tříd. Pokud fake není vůbec potřeba (test kontroluje pouze jeden scénář s pevnými daty) — použijte stub. Pokud test kontroluje, zda byla metoda volána s určitými parametry — použijte mock. Neoptimalizujte výběr předem: napište fake, a pokud se ukáže jako nadbytečný, nahraďte ho stub v konkrétním testu.

Vytváření Fake-objektů na Androidu pro Room a Retrofit

Fake-repozitář pro Room — typický příklad fake na Androidu. Produkční implementace UserRepository používá Room DAO s SQLite dotazy. Fake verze ukládá data v MutableList nebo HashMap a implementuje stejné metody: getUser(id), saveUser(user), deleteUser(id). Fake obsahuje logiku vyhledávání, filtrování a řazení — stejnou jako v produkčním repozitáři, ale bez SQL. To umožňuje testovat ViewModel a UseCase bez konfigurace Room databáze.

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 pro Retrofit API — místo MockWebServer (který je stub, ne fake) lze vytvořit implementaci ApiService, která vrací data z in-memory kolekce. Rozdíl: MockWebServer zachycuje HTTP a vrací JSON, zatímco fake-ApiService pracuje na úrovni Kotlin rozhraní bez serializace. Fake je rychlejší (žádné parsování JSON) a jednodušší na ladění (pracuje ve stejném procesu, typovaný). Vhodný pro testy, kde HTTP sémantika (stavové kódy, hlavičky) není důležitá.

FakeSharedPreferences pro rychlé testy

— další častý scénář. Produkční SharedPreferences zapisují na disk přes commit/apply. Fake verze ukládá páry klíč-hodnota v HashMap a okamžitě vrací data. Podporuje stejné metody: getString, putString, getInt, putInt, clear. Pro Jetpack DataStore je analog FakeDataStore s in-memory úložištěm. Takové fake urychlují testy desetinásobně, protože nejsou žádné operace zápisu na disk.

Fake implementace na iOS s in-memory úložišti

Fake ve Swift — staví se přes protokoly. Produkční třída implementuje protokol se skutečnou logikou (CoreData, URLSession). Fake struktura implementuje stejný protokol s in-memory úložištěm a zjednodušenou logikou. Swift je jazyk s hodnotovou sémantikou, proto jsou fake struktury neměnné a bezpečné ve vícevláknových testech. To dává výhodu oproti Android analogům: přístup k in-memory datům není třeba synchronizovat.

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 pro CoreData — v iOS projektech lze vytvořit in-memory NSPersistentContainer nastavením description.type = NSInMemoryStoreType. Toto je plnohodnotný CoreData stack pracující v paměti. Takový fake umožňuje testovat NSFetchRequest, predikáty a řazení bez vytváření SQLite souboru. Rychlost: testy na in-memory CoreData se provádějí 5-10 krát rychleji než na diskovém analogu. Nevýhoda: NSManagedObjectModel je třeba konfigurovat pokaždé.

FakeURLProtocol — podtřída URLProtocol pro zachycování síťových požadavků na iOS. Registruje se přes URLProtocol.registerClass(fakeProtocol). Uvnitř obsahuje in-memory slovník URL -> Data a vrací data bez skutečného požadavku. Rozdíl od stub: FakeURLProtocol může kontrolovat tělo požadavku, hlavičky a vracet různé odpovědi v závislosti na vstupních datech. Toto je fake, protože obsahuje logiku směrování požadavků.

Vzory použití Fake v mobilních projektech

Fake jako Test Fixture — přesuňte fake třídy do společného testovacího modulu (androidTest/sharedTest nebo TestSupport). Všechny testy v projektu používají stejný InMemoryUserRepository. To eliminuje duplicitu konfigurace mock objektů v každém testu a zaručuje jednotné chování. Změna logiky fake aktualizuje všechny testy současně. V IT Sectr ukládáme fake třídy v sharedTest/java/com/itSectr/fake/ a připojujeme přes implementation project(:sharedTest).

Fake s předem nastavenými daty — často testy potřebují repozitář, který již obsahuje některé záznamy. Řešení: tovární metoda fakeWithData(vararg items) nebo vestavěná metoda addDefaultData(). Továrna vytvoří fake, naplní ho typickými daty a vrátí objekt připravený k použití. To snižuje boilerplate v testech: místo konfigurace mock volání test jednoduše volá FakeUserRepository.withUsers(alice, bob).

Fake s počítáním volání — někdy je třeba zkontrolovat nejen stav, ale také počet volání. Fake může obsahovat čítače: saveCallCount, getUserCallCount. Test zkontroluje čítač po provedení. Toto je kompromis mezi čistým fake (kontrola stavu) a mock (kontrola interakce). Čítače nekontrolují argumenty a pořadí volání — pouze počet. Pro kontrolu argumentů použijte mock.

Fake s Callback — pro testování asynchronních scénářů může fake přijímat callback při každém volání: beforeGetUser, afterSaveUser. To umožňuje simulovat zpoždění, chyby nebo kontrolovat mezistavy. Tento přístup je užitečný pro testování stavů načítání UI: fake udělá pauzu 100 ms a test zkontroluje, zda obrazovka zobrazuje loader. V produkci callback neexistuje — je to čistě testovací funkcionalita.

Často kladené otázky

Čím se Fake liší od Stub?

Fake obsahuje fungující logiku — filtruje, řadí, počítá. Stub vrací pouze předdefinované odpovědi bez logiky. Pokud má objekt větvení (if/else, when) — je to fake. Pokud obsahuje pouze return values — je to stub. Fake je dražší na údržbu, ale poskytuje realističtější testy.

Kdy může být fake škodlivý?

Když se logika fake neshoduje s produkční logikou. Například FakeUserRepository používá case-sensitive vyhledávání, zatímco produkce case-insensitive. Test projde, ale ve skutečnosti je chyba. Řešení: testujte logiku fake samostatně nebo používejte fakes pouze pro rozhraní s jednoduchou logikou (CRUD operace). Pro složitou logiku pište integrační testy s reálnou databází.

Je Fake totéž co in-memory database?

In-memory database — jedna z variant fake. Room.inMemoryDatabaseBuilder() vytváří in-memory SQLite, který se chová jako produkční databáze. Toto je plnohodnotný fake. Ale fake může být také na úrovni repozitáře (bez SQL) a na úrovni sítě (FakeApiService). In-memory databáze je speciální případ fake, kdy je logika maximálně blízká reálné.

Lze kombinovat Fake a Mock v jednom testu?

Ano, ale opatrně. Fake pro repozitář (data), Mock pro AnalyticsTracker (ověření událostí). Rozdělení podle vrstev: fake pro datovou vrstvu, mock pro vrstvu analytiky/logování. Nedělejte jeden objekt současně fake a mock — to porušuje princip jedné odpovědnosti a mate test.

Jak testovat samotný Fake?

Testujte fake stejnými testy jako produkční implementaci. Pokud máte UserRepositoryTest, který kontroluje save, get, delete — spusťte ho dvakrát: s FakeUserRepository a s RealUserRepository. To zaručuje, že fake opakuje chování produkční třídy. Pokud se fake začne chovat jinak — test selže na obou implementacích.

Shrnutí

  • Fake — fungující zjednodušená implementace závislosti se skutečnou obchodní logikou a in-memory úložištěm
  • Rozdíl od Stub — fake obsahuje logiku (filtrování, řazení), stub pouze vrací data
  • Rychlost — fake pracuje 100-1000 krát rychleji než produkční implementace bez I/O operací
  • Android — InMemoryUserRepository, FakeDataStore, in-memory Room přes Room.inMemoryDatabaseBuilder
  • iOS — protokolově založený fake, in-memory CoreData, FakeURLProtocol pro HTTP zachycování
  • Nejlepší praxe — přesuňte fake do společného testovacího modulu a používejte ve všech testech projektu
  • Testujte fake — spouštějte stejné testy na fake a produkční implementaci pro kontrolu konzistence

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také