Fake — vad är det, syfte och hur man använder i testning

Författare: IT Sectr Publicerad: 2026-04-10 Lästid: 9 min

Fake (fejk) — en fungerande förenklad implementering av ett beroende som beter sig som en verklig komponent, men använder in-memory lagring eller andra lätta mekanismer istället för produktionsinfrastruktur. Till skillnad från stub innehåller fake verklig affärslogik — sortering, filtrering, aggregering — bara utan externa effekter. In-memory databas istället för Room eller HashMap istället för SharedPreferences — klassiska exempel. Mer i Martin Fowler’s klassificering av test doubles.

Huvudpunkter

  • Fake — förenklad fungerande implementering med verklig logik, men utan externa beroenden
  • In-memory lagring — fake-repository lagrar data i HashMap, inte i databasen
  • Skillnad från Stub — stub returnerar fast data, fake innehåller körbar logik
  • Android — InMemoryUserRepository som Fake för testning av ViewModel och UseCase
  • iOS — FakeNetworkSession med URLProtocol och testdata istället för verklig server

Vad är Fake och varför behövs det i testning?

Fake — en fullständig men lätt implementering av ett gränssnitt, lämplig för testning. Termen introducerades av Gerard Meszaros (2007) i boken «xUnit Test Patterns». Till skillnad från stub, som returnerar strikt fördefinierade svar, innehåller fake körbar kod: den kan sortera en lista, filtrera efter villkor, räkna poster. Den enda skillnaden från produktionsimplementeringen — fake arbetar med in-memory data och utför inte verkliga I/O-operationer.

Främsta fördelen — hastighet. Tester med fake utförs på millisekunder, eftersom det inte finns någon åtkomst till disk, nätverk eller databas. In-memory HashMap fungerar 100-1000 gånger snabbare än Room eller CoreData. Samtidigt kontrollerar fake verklig affärslogik: sortering, filtrering, aggregering — allt som stub inte kan kontrollera, eftersom stub bara returnerar vad den blir tillsagd. Fake ger förtroende för att koden bearbetar data korrekt, inte bara tar emot ett fördefinierat svar.

När Fake är att föredra framför Stub

Fake är att föredra framför Stub — om den testade komponenten utför flera operationer på data (hämtade, filtrerade, sorterade, sparade), kommer stub att kräva konfiguration av varje anrop separat. Fake innehåller logiken internt — testet anropar helt enkelt metoder och kontrollerar resultatet. Hos IT Sectr använder vi fake för alla repositories i enhetstester: fake-repository med HashMap täcker 90% av scenarierna utan konfiguration av Mockito eller MockK.

Fake vs Stub vs Mock: när ska man välja vad

Urvalskriterium — bestäm vad testet kontrollerar: tillstånd eller interaktion. Om testet kontrollerar tillstånd (arbetsresultatet) och använder logik — behövs fake. Om testet bara behöver indata utan logik — räcker stub. Om testet kontrollerar att en metod har anropats — behövs mock. Att blanda test doubles-typer i ett test försvårar förståelsen och ökar skörheten.

KriteriumFakeStubMock
Förekomst av logikJa (förenklad)NejNej
HastighetHögMaximalHög
BeteendekontrollIndirektNejJa (verify)
UnderhållEn klass per gränssnittKonfiguration per testKonfiguration per test
RealismHög (koden fungerar)Låg (fast data)Medel
Risk för falsklarmLågMedelHög (sköra tester)

Antimönster: Fake som inte är fake — ett vanligt misstag när utvecklaren kallar ett objekt fake som egentligen är stub eller mock. Om din InMemoryUserRepository inte innehåller logik (filtrering, sortering) — är detta inte fake, utan stub med in-memory lagring. Fake skiljer sig från stub just genom närvaron av körbar logik. Om fake-repository bara returnerar vad som lagts i det och inte bearbetar data — använd mock eller stub.

Praktisk regel för att välja test double

Praktisk rekommendation — börja med fake för varje repository eller tjänst. Om fake är mer komplex än 50 rader — dela upp i flera klasser. Om fake inte alls behövs (testet kontrollerar bara ett scenario med fast data) — använd stub. Om testet kontrollerar om en metod anropades med specifika parametrar — använd mock. Optimera inte valet i förväg: skriv fake, och om det visar sig vara överflödigt, ersätt det med stub i det specifika testet.

Skapa Fake-objekt på Android för Room och Retrofit

Fake-repository för Room — typiskt exempel på fake på Android. Produktionsimplementeringen av UserRepository använder Room DAO med SQLite-frågor. Fake-versionen lagrar data i MutableList eller HashMap och implementerar samma metoder: getUser(id), saveUser(user), deleteUser(id). Fake innehåller sök-, filtrerings- och sorteringslogik — samma som i produktionsrepositoryt, men utan SQL. Detta gör det möjligt att testa ViewModel och UseCase utan konfiguration av Room-databasen.

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 för Retrofit API — istället för MockWebServer (som är stub, inte fake) kan en implementering av ApiService skapas som returnerar data från en in-memory samling. Skillnad: MockWebServer fångar upp HTTP och returnerar JSON, medan fake-ApiService arbetar på Kotlin-gränssnittsnivå utan serialisering. Fake är snabbare (ingen JSON-tolkning) och enklare att felsöka (arbetar i samma process, typad). Lämplig för tester där HTTP-semantik (statuskoder, rubriker) inte är viktig.

FakeSharedPreferences för snabba tester

— ytterligare ett vanligt scenario. Produktionens SharedPreferences skriver till disk via commit/apply. Fake-versionen lagrar nyckel-värdepar i HashMap och returnerar omedelbart data. Stöder samma metoder: getString, putString, getInt, putInt, clear. För Jetpack DataStore är motsvarigheten FakeDataStore med in-memory lagring. Sådana fake påskyndar tester tiotals gånger eftersom det inte finns några skrivoperationer till disk.

Fake-implementeringar på iOS med in-memory lagring

Fake i Swift — byggs via protokoll. Produktionsklassen implementerar protokollet med verklig logik (CoreData, URLSession). Fake-strukturen implementerar samma protokoll med in-memory lagring och förenklad logik. Swift är ett språk med värdessemantik, så fake-strukturer är oföränderliga och säkra i flertrådade tester. Detta ger en fördel jämfört med Android-motsvarigheter: åtkomst till in-memory data behöver inte synkroniseras.

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 för CoreData — i iOS-projekt kan en in-memory NSPersistentContainer skapas genom att ställa in description.type = NSInMemoryStoreType. Detta är en fullständig CoreData-stack som arbetar i minnet. En sådan fake gör det möjligt att testa NSFetchRequest, predikat och sorteringar utan att skapa en SQLite-fil. Hastighet: tester på in-memory CoreData utförs 5-10 gånger snabbare än på disk-motsvarigheten. Nackdel: NSManagedObjectModel måste konfigureras varje gång.

FakeURLProtocol — en underklass av URLProtocol för att fånga upp nätverksförfrågningar på iOS. Registreras via URLProtocol.registerClass(fakeProtocol). Inuti innehåller den en in-memory ordbok URL -> Data och returnerar data utan verklig förfrågan. Skillnad från stub: FakeURLProtocol kan kontrollera förfrågans innehåll, rubriker och returnera olika svar beroende på indata. Detta är fake eftersom det innehåller logik för routning av förfrågningar.

Mönster för användning av Fake i mobilprojekt

Fake som Test Fixture — flytta fake-klasser till en gemensam testmodul (androidTest/sharedTest eller TestSupport). Alla tester i projektet använder samma InMemoryUserRepository. Detta eliminerar dubbelarbete med konfiguration av mock-objekt i varje test och garanterar enhetligt beteende. Ändring av fake-logik uppdaterar alla tester samtidigt. Hos IT Sectr lagrar vi fake-klasser i sharedTest/java/com/itSectr/fake/ och ansluter via implementation project(:sharedTest).

Fake med förinställd data — ofta behöver tester ett repository som redan innehåller vissa poster. Lösning: fabriksmetod fakeWithData(vararg items) eller inbyggd metod addDefaultData(). Fabriken skapar fake, fyller den med typisk data och returnerar ett redo-att-använda objekt. Detta minskar boilerplate i tester: istället för att konfigurera mock-anrop, anropar testet helt enkelt FakeUserRepository.withUsers(alice, bob).

Fake med anropsräkning — ibland måste man kontrollera inte bara tillståndet utan också antalet anrop. Fake kan innehålla räknare: saveCallCount, getUserCallCount. Testet kontrollerar räknaren efter exekvering. Detta är en kompromiss mellan ren fake (tillståndskontroll) och mock (interaktionskontroll). Räknare kontrollerar inte argument och anropsordning — bara antalet. För argumentkontroll, använd mock.

Fake med Callback — för testning av asynkrona scenarier kan fake acceptera en callback vid varje anrop: beforeGetUser, afterSaveUser. Detta gör det möjligt att simulera förseningar, fel eller kontrollera mellanliggande tillstånd. Detta tillvägagångssätt är användbart för testning av UI-laddningstillstånd: fake pausar i 100 ms, och testet kontrollerar om skärmen visar en laddningsindikator. I produktion finns callback inte — det är ren testfunktionalitet.

Vanliga frågor

Vad är skillnaden mellan Fake och Stub?

Fake innehåller fungerande logik — filtrerar, sorterar, räknar. Stub returnerar bara fördefinierade svar utan logik. Om ett objekt har förgreningar (if/else, when) — är det fake. Om det bara innehåller return values — är det stub. Fake är dyrare att underhålla, men ger mer realistiska tester.

När kan fake vara skadligt?

När fake-logiken inte överensstämmer med produktionslogiken. Till exempel använder FakeUserRepository case-sensitive sökning, medan produktionen använder case-insensitive. Testet godkänns, men i verkligheten finns en bugg. Lösning: testa fake-logiken separat eller använd fakes endast för gränssnitt med enkel logik (CRUD-operationer). För komplex logik, skriv integrationstester med en riktig databas.

Är Fake samma sak som in-memory database?

In-memory database — en av varianterna av fake. Room.inMemoryDatabaseBuilder() skapar en in-memory SQLite som beter sig som en produktionsdatabas. Detta är en fullvärdig fake. Men fake kan också vara på repository-nivå (utan SQL) och på nätverksnivå (FakeApiService). In-memory databas är ett speciellt fall av fake där logiken är maximalt nära den verkliga.

Kan man kombinera Fake och Mock i ett test?

Ja, men försiktigt. Fake för repository (data), Mock för AnalyticsTracker (händelseverifiering). Uppdelning per lager: fake för datalagret, mock för analys-/loggningslagret. Gör inte ett objekt samtidigt fake och mock — detta bryter mot principen om enskilt ansvar och förvirrar testet.

Hur testar man själva Fake?

Testa fake med samma tester som produktionsimplementeringen. Om du har UserRepositoryTest som kontrollerar save, get, delete — kör det två gånger: med FakeUserRepository och med RealUserRepository. Detta garanterar att fake upprepar produktionsklassens beteende. Om fake börjar bete sig annorlunda — kommer testet att misslyckas på båda implementeringarna.

Sammanfattning

  • Fake — fungerande förenklad implementering av beroende med verklig affärslogik och in-memory lagring
  • Skillnad från Stub — fake innehåller logik (filtrering, sortering), stub returnerar bara data
  • Hastighet — fake fungerar 100-1000 gånger snabbare än produktionsimplementering utan I/O-operationer
  • Android — InMemoryUserRepository, FakeDataStore, in-memory Room via Room.inMemoryDatabaseBuilder
  • iOS — protokollbaserad fake, in-memory CoreData, FakeURLProtocol för HTTP-avlyssning
  • Bästa praxis — flytta fake till en gemensam testmodul och använd i alla tester i projektet
  • Testa fake — kör samma tester på fake och produktionsimplementering för konsistenskontroll

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också