Fake — wat is het, doel en hoe te gebruiken in testen

Auteur: IT Sectr Gepubliceerd: 2026-04-10 Leestijd: 9 min

Fake (feek) — een werkende vereenvoudigde implementatie van een afhankelijkheid die zich gedraagt als een echte component, maar in-memory opslag of andere lichte mechanismen gebruikt in plaats van productie-infrastructuur. In tegenstelling tot stub bevat fake echte bedrijfslogica — sorteren, filteren, aggregeren — alleen zonder externe effecten. In-memory database in plaats van Room of HashMap in plaats van SharedPreferences — klassieke voorbeelden. Meer in classificatie van test doubles door Martin Fowler.

Belangrijkste

  • Fake — vereenvoudigde werkende implementatie met echte logica, maar zonder externe afhankelijkheden
  • In-memory opslag — fake-repository slaat gegevens op in HashMap, niet in database
  • Verschil met Stub — stub retourneert vaste gegevens, fake bevat uitvoerbare logica
  • Android — InMemoryUserRepository als Fake voor het testen van ViewModel en UseCase
  • iOS — FakeNetworkSession met URLProtocol en testgegevens in plaats van echte server

Wat is Fake en waarom is het nodig in testen?

Fake — een volledige, maar lichte implementatie van een interface, geschikt voor testen. De term is geïntroduceerd door Gerard Meszaros (2007) in het boek «xUnit Test Patterns». In tegenstelling tot stub, die strikt vooraf bepaalde antwoorden retourneert, bevat fake uitvoerbare code: het kan een lijst sorteren, filteren op voorwaarde, het aantal records tellen. Het enige verschil met de productie-implementatie — fake werkt met in-memory gegevens en voert geen echte I/O-bewerkingen uit.

Belangrijkste voordeel — snelheid. Testen met fake worden in milliseconden uitgevoerd, omdat er geen toegang is tot schijf, netwerk of database. In-memory HashMap werkt 100-1000 keer sneller dan Room of CoreData. Tegelijkertijd controleert fake echte bedrijfslogica: sorteren, filteren, aggregeren — alles wat stub niet kan controleren, omdat stub alleen retourneert wat hem is verteld. Fake geeft vertrouwen dat de code gegevens correct verwerkt, niet alleen een vooraf bepaald antwoord ontvangt.

Wanneer Fake de voorkeur heeft boven Stub

Fake heeft de voorkeur boven Stub — als de geteste component meerdere bewerkingen op gegevens uitvoert (opgehaald, gefilterd, gesorteerd, opgeslagen), vereist stub configuratie van elke aanroep afzonderlijk. Fake bevat de logica intern — de test roept eenvoudig methoden aan en controleert het resultaat. Bij IT Sectr gebruiken we fake voor alle repositories in unit tests: fake-repository met HashMap dekt 90% van scenario's zonder configuratie van Mockito of MockK.

Fake vs Stub vs Mock: wanneer wat te kiezen

Selectiecriterium — bepaal wat de test controleert: status of interactie. Als de test status (het resultaat) controleert en logica gebruikt — is fake nodig. Als de test alleen invoergegevens zonder logica nodig heeft — is stub voldoende. Als de test het feit van een methode-aanroep controleert — is mock nodig. Het mengen van test doubles types in één test bemoeilijkt het begrip en verhoogt de kwetsbaarheid.

CriteriumFakeStubMock
Aanwezigheid van logicaJa (vereenvoudigd)NeeNee
SnelheidHoogMaximaalHoog
GedragscontroleIndirectNeeJa (verify)
OnderhoudÉén klasse per interfaceConfiguratie per testConfiguratie per test
RealismeHoog (code werkt)Laag (vaste gegevens)Gemiddeld
Risico op valse alarmenLaagGemiddeldHoog (kwetsbare testen)

Antipatroon: Fake die geen fake is — een veelgemaakte fout waarbij een ontwikkelaar een object fake noemt dat eigenlijk stub of mock is. Als InMemoryUserRepository geen logica (filteren, sorteren) bevat — is dit geen fake, maar stub met in-memory opslag. Fake verschilt van stub juist door de aanwezigheid van uitvoerbare logica. Als een fake-repository gewoon retourneert wat erin is gestopt en geen gegevens verwerkt — gebruik dan mock of stub.

Praktische regel voor het kiezen van test double

Praktische aanbeveling — begin met fake voor elke repository of service. Als fake complexer is dan 50 regels — verdeel het in meerdere klassen. Als fake helemaal niet nodig is (test controleert slechts één scenario met vaste gegevens) — gebruik stub. Als de test controleert of een methode met specifieke parameters is aangeroepen — gebruik mock. Optimaliseer de keuze niet vooraf: schrijf fake, en als het overbodig blijkt, vervang het dan door stub in de specifieke test.

Fake-objecten maken op Android voor Room en Retrofit

Fake-repository voor Room — typisch voorbeeld van fake op Android. De productie-implementatie van UserRepository gebruikt Room DAO met SQLite-query's. De fake-versie slaat gegevens op in MutableList of HashMap en implementeert dezelfde methoden: getUser(id), saveUser(user), deleteUser(id). Fake bevat zoek-, filter- en sorteerlogica — dezelfde als in de productie-repository, maar zonder SQL. Dit maakt het mogelijk om ViewModel en UseCase te testen zonder configuratie van de 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 voor Retrofit API — in plaats van MockWebServer (die stub is, geen fake) kan een implementatie van ApiService worden gemaakt die gegevens uit een in-memory collectie retourneert. Verschil: MockWebServer onderschept HTTP en retourneert JSON, terwijl fake-ApiService op Kotlin-interface-niveau werkt zonder serialisatie. Fake is sneller (geen JSON-parsing) en eenvoudiger te debuggen (werkt in hetzelfde proces, getypeerd). Geschikt voor tests waar HTTP-semantiek (statuscodes, headers) niet belangrijk is.

FakeSharedPreferences voor snelle tests

— nog een veelvoorkomend scenario. Productie SharedPreferences schrijft via commit/apply naar schijf. De fake-versie slaat sleutel-waardeparen op in HashMap en retourneert direct gegevens. Ondersteunt dezelfde methoden: getString, putString, getInt, putInt, clear. Voor Jetpack DataStore is de analoog FakeDataStore met in-memory opslag. Zulke fakes versnellen tests tientallen keren, omdat er geen schijfschrijfbewerkingen zijn.

Fake-implementaties op iOS met in-memory opslagen

Fake in Swift — wordt gebouwd via protocollen. De productieklasse implementeert het protocol met echte logica (CoreData, URLSession). De fake-structuur implementeert hetzelfde protocol met in-memory opslag en vereenvoudigde logica. Swift is een taal met waarde-semantiek, dus fake-structuren zijn onveranderlijk en veilig in multi-threaded tests. Dit geeft een voordeel ten opzichte van Android-analogen: toegang tot in-memory gegevens hoeft niet te worden gesynchroniseerd.

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 voor CoreData — in iOS-projecten kan een in-memory NSPersistentContainer worden gemaakt door description.type = NSInMemoryStoreType in te stellen. Dit is een volledige CoreData-stack die in het geheugen werkt. Zo'n fake maakt het mogelijk om NSFetchRequest, predicaten en sorteringen te testen zonder een SQLite-bestand te maken. Snelheid: tests op in-memory CoreData worden 5-10 keer sneller uitgevoerd dan op de schijf-analoog. Nadeel: NSManagedObjectModel moet elke keer worden geconfigureerd.

FakeURLProtocol — een subclass van URLProtocol voor het onderscheppen van netwerkverzoeken op iOS. Wordt geregistreerd via URLProtocol.registerClass(fakeProtocol). Bevat intern een in-memory woordenboek URL -> Data en retourneert gegevens zonder echt verzoek. Verschil met stub: FakeURLProtocol kan de verzoekinhoud, headers controleren en verschillende antwoorden retourneren afhankelijk van de invoergegevens. Dit is fake omdat het routeringslogica voor verzoeken bevat.

Patronen voor het gebruik van Fake in mobiele projecten

Fake als Test Fixture — verplaats fake-klassen naar een gedeelde testmodule (androidTest/sharedTest of TestSupport). Alle tests in het project gebruiken dezelfde InMemoryUserRepository. Dit elimineert het dupliceren van mock-configuratie in elke test en garandeert uniform gedrag. Wijziging van de fake-logica werkt alle tests tegelijk bij. Bij IT Sectr bewaren we fake-klassen in sharedTest/java/com/itSectr/fake/ en koppelen we via implementation project(:sharedTest).

Fake met vooraf ingestelde gegevens — vaak hebben tests een repository nodig die al enkele records bevat. Oplossing: fabrieksmethode fakeWithData(vararg items) of ingebouwde methode addDefaultData(). De fabriek maakt fake, vult deze met typische gegevens en retourneert een gebruiksklaar object. Dit vermindert boilerplate in tests: in plaats van mock-aanroepen te configureren, roept de test eenvoudig FakeUserRepository.withUsers(alice, bob) aan.

Fake met aantallen aanroepen — soms moet niet alleen de status, maar ook het aantal aanroepen worden gecontroleerd. Fake kan tellers bevatten: saveCallCount, getUserCallCount. De test controleert de teller na uitvoering. Dit is een compromis tussen pure fake (statuscontrole) en mock (interactiecontrole). Tellers controleren geen argumenten en aanroepvolgorde — alleen het aantal. Gebruik mock voor argumentcontrole.

Fake met Callback — voor het testen van asynchrone scenario's kan fake bij elke aanroep een callback accepteren: beforeGetUser, afterSaveUser. Dit maakt het mogelijk om vertragingen, fouten te simuleren of tussenliggende statussen te controleren. Deze aanpak is nuttig voor het testen van UI-laadstatussen: fake pauzeert 100 ms, en de test controleert of het scherm een loader toont. In productie is callback afwezig — het is puur testfunctionaliteit.

Veelgestelde vragen

Wat is het verschil tussen Fake en Stub?

Fake bevat werkende logica — filtert, sorteert, telt. Stub retourneert alleen vooraf bepaalde antwoorden zonder logica. Als een object vertakkingen heeft (if/else, when) — is het fake. Als het alleen return values bevat — is het stub. Fake is duurder in onderhoud, maar geeft realistischere tests.

Wanneer kan fake schadelijk zijn?

Wanneer de fake-logica niet overeenkomt met de productielogica. Bijvoorbeeld, FakeUserRepository gebruikt case-sensitive zoeken, terwijl productie case-insensitive is. De test slaagt, maar in werkelijkheid is er een bug. Oplossing: test de fake-logica apart of gebruik fakes alleen voor interfaces met eenvoudige logica (CRUD-bewerkingen). Schrijf voor complexe logica integratietests met een echte database.

Is Fake hetzelfde als in-memory database?

In-memory database — een van de varianten van fake. Room.inMemoryDatabaseBuilder() creëert een in-memory SQLite die zich gedraagt als een productiedatabase. Dit is een volwaardige fake. Maar fake kan ook op repository-niveau (zonder SQL) en op netwerkniveau (FakeApiService) zijn. In-memory database is een speciaal geval van fake waarbij de logica maximaal dicht bij de echte ligt.

Kunnen Fake en Mock worden gecombineerd in één test?

Ja, maar voorzichtig. Fake voor repository (gegevens), Mock voor AnalyticsTracker (gebeurtenisverificatie). Scheiding per laag: fake voor de gegevenslaag, mock voor de analyse-/loglaag. Maak niet één object tegelijk fake en mock — dit schendt het Single Responsibility Principle en verwart de test.

Hoe test je Fake zelf?

Test fake met dezelfde tests als de productie-implementatie. Als je UserRepositoryTest hebt die save, get, delete controleert — voer het twee keer uit: met FakeUserRepository en met RealUserRepository. Dit garandeert dat fake het gedrag van de productieklasse herhaalt. Als fake zich anders gaat gedragen — zal de test op beide implementaties falen.

Samenvatting

  • Fake — werkende vereenvoudigde implementatie van een afhankelijkheid met echte bedrijfslogica en in-memory opslag
  • Verschil met Stub — fake bevat logica (filteren, sorteren), stub retourneert alleen gegevens
  • Snelheid — fake werkt 100-1000 keer sneller dan productie-implementatie zonder I/O-bewerkingen
  • Android — InMemoryUserRepository, FakeDataStore, in-memory Room via Room.inMemoryDatabaseBuilder
  • iOS — protocol-based fake, in-memory CoreData, FakeURLProtocol voor HTTP-onderschepping
  • Beste praktijk — verplaats fake naar een gedeelde testmodule en gebruik in alle tests van het project
  • Test fake — voer dezelfde tests uit op fake en productie-implementatie voor consistentiecontrole

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook