Stub: wat is het, soorten en toepassing in testen

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

Stub (testvervanger, stub) — een testobject dat vooraf gedefinieerde antwoorden teruggeeft op methodeaanroepen in plaats van een echte implementatie. In mobiele ontwikkeling isoleren stubs de geteste module van netwerkverzoeken, databases en het bestandssysteem, waardoor logica kan worden gecontroleerd zonder omgevingsconfiguratie. In tegenstelling tot mock controleert stub geen gedrag — het levert alleen gegevens. Meer in Martin Fowler's artikel over test doubles.

Belangrijkste punten

  • Stub — vervanger die vaste waarden retourneert op methodeaanroepen zonder logica
  • Isolatie — stubs schakelen echte afhankelijkheden uit: API, database, bestanden, sensoren
  • Verschil met Mock — stub verifieert geen aanroepen, het vervangt alleen het antwoord
  • Android — MockWebServer (OkHttp) als stub voor HTTP, MockK.constantAnswer voor Kotlin
  • iOS — OCMock en Swift-protocollen met testimplementaties als stubs

Wat is Stub en hoe verschilt het van andere test doubles?

Stub — is een vervangend object dat de echte afhankelijkheid in de test vervangt en vooraf bepaalde waarden retourneert op specifieke aanroepen. De term is geïntroduceerd in de classificatie van Gerard Meszaros (2007) in het boek „xUnit Test Patterns". Stub behoort tot de categorie test doubles — objecten die echte componenten vervangen tijdens het testen. Het hoofddoel van een stub is om het geteste blok van voorspelbare gegevens te voorzien, waarbij onzekerheid van externe systemen wordt weggenomen.

Werkingsprincipe — de test configureert de stub voor uitvoering: „wanneer de methode getUsers() wordt aangeroepen, retourneer deze lijst met gebruikers". Stub bevat geen bedrijfslogica, controleert niet de volgorde van aanroepen en registreert geen geschiedenis. Het staat gewoon op de plaats van de echte component en geeft wat het is verteld. In de context van Android-testen betekent dit dat de OkHttp-client geen echt verzoek naar de server stuurt, maar het antwoord krijgt van MockWebServer die als stub is geconfigureerd.

  • Stub — retourneert gegevens, controleert geen aanroepen
  • Mock — retourneert gegevens en verifieert gedrag (verify)
  • Fake — werkende vereenvoudigde implementatie met echte logica
  • Spy — omhult het echte object en registreert aanroepen
  • Dummy — wordt doorgegeven maar niet gebruikt (null, leeg object)

Wanneer gebruiken — stubs zijn optimaal voor het testen van de UI-laag (ViewModel, Presenter) en bedrijfslogica (UseCase, Interactor), waar de reactie op specifieke gegevens moet worden gecontroleerd: lijst leeg, server retourneerde fout 500, token verlopen. Elk geval waarin de test een specifieke invoertoestand vereist, is een taak voor stub. Voor elk testscenario wordt een eigen stub-configuratie gemaakt, wat tests leesbaar en voorspelbaar maakt.

Classificatie van test doubles volgens Meszaros

Gerard Meszaros (2007) identificeerde in het boek „xUnit Test Patterns" vijf soorten test doubles: dummy, stub, spy, mock, fake. Elk type lost zijn eigen taak op. Dummy — wordt doorgegeven maar niet gebruikt. Stub — retourneert gegevens. Spy — registreert aanroepen. Mock — verifieert gedrag. Fake — bevat vereenvoudigde logica. Inzicht in deze classificatie helpt de ontwikkelaar het juiste gereedschap te kiezen voor elk testscenario.

Waar worden stubs gebruikt in het testen van mobiele applicaties

Stubs voor netwerkverzoeken

Netwerkverzoeken — het meest voorkomende scenario voor stubs. De applicatie doet HTTP-aanroepen naar de API en in de test moet de reactie op verschillende antwoorden worden gecontroleerd: succesvolle JSON, fout 401 (ongeautoriseerd), time-out, lege array. MockWebServer (OkHttp) op Android en URLProtocol (iOS) fungeren als stubs en retourneren vooraf gedefinieerde HTTP-antwoorden zonder echte verbinding met de server. Dit versnelt tests van seconden naar milliseconden.

Database — Room (Android) en CoreData (iOS) hebben in-memory varianten, maar het configureren ervan kost nog steeds tijd. Stub retourneert in plaats van de repository vooraf voorbereide Entity-lijsten zonder de database aan te raken. Dit is vooral effectief voor het testen van ViewModel, waar sorteren, filteren of gegevenstransformatie moet worden gecontroleerd. De test wordt in milliseconden uitgevoerd, ongeacht de hoeveelheid gegevens.

Systeemdiensten — LocationManager, SensorManager, SharedPreferences vereisen een echt apparaat of emulator. Stub voor LocationProvider retourneert opgegeven coördinaten, voor SensorManager — vaste accelerometerwaarden. Op iOS is de analoog CLLocationManager met testimplementatie van de delegate. Zonder stubs vereisen dergelijke tests een fysiek apparaat met specifieke omstandigheden.

Bestandssysteem en cache — het laden van afbeeldingen, cachen van antwoorden, werken met configuratiebestanden — al deze bewerkingen zijn afhankelijk van de schijfstatus. Stub voor FileManager of ImageCache retourneert succes/fout zonder echte bestanden te lezen. Dit elimineert valse testfouten door niet-overeenkomende paden of rechten op verschillende ontwikkelaarsmachines.

Stub vs Mock vs Fake: belangrijkste verschillen

Verdeling van verantwoordelijkheden — drie soorten test doubles lossen verschillende taken op. Stub: „geef me gegevens". Mock: „controleer of ik ben aangeroepen". Fake: „ik werk als een echte, alleen eenvoudiger". Het verschil is kritisch voor de leesbaarheid van tests: als een test mock gebruikt waar stub nodig is, wordt deze overladen met verify-aanroepen die geen verband houden met het geteste scenario.

KenmerkStubMockFake
DoelGegevens leverenInteractie verifiërenVereenvoudigde implementatie
LogicaNeeNeeJa (maar vereenvoudigd)
VerificatieNeeJa (verify)Indirect (via toestand)
FlexibiliteitLaag — vaste antwoordenGemiddeldHoog — logica past zich aan
SnelheidMaximaalHoogGemiddeld
VoorbeeldMockWebServer retourneert JSONMockito.verify(repository).save()InMemoryRepository met HashMap

Praktische regel — als de test controleert welke gegevens de geteste component heeft ontvangen — gebruik stub. Als de test controleert of de component de afhankelijkheidsmethode met de juiste argumenten heeft aangeroepen — gebruik mock. Als u gewoon de database wilt vervangen door een hash-tabel — is dit fake. Het mengen van typen in één test maakt deze breekbaar: bij wijziging van de implementatie moet zowel de stub als de verify-logica worden herschreven.

Antipatroon: Stub met verify

Stub met verify — een veelgemaakte fout wanneer een ontwikkelaar een stub configureert en vervolgens verify(stub).method() toevoegt. Stub mag per definitie niet worden geverifieerd — voor verificatie is er mock. Als u moet controleren of een methode met specifieke argumenten is aangeroepen, gebruik dan Mockito.mock() in plaats van Mockito.stub(). Deze scheiding houdt de intentie van de test duidelijk voor andere ontwikkelaars.

Implementatie van stubs op Android met MockWebServer en MockK

MockWebServer — OkHttp-bibliotheek voor het maken van HTTP-stubs op Android en JVM. Het start een lokale HTTP-server op een opgegeven poort die verzoeken van de OkHttp-client onderschept en vooraf gedefinieerde antwoorden retourneert. Configuratie duurt drie regels: server maken, antwoord in de wachtrij plaatsen (enqueue), starten. De test kan achtereenvolgens meerdere antwoorden in de wachtrij plaatsen voor scenario's met paginering of herhaalde pogingen.

kotlin
class UserRepositoryTest {

    private val server = MockWebServer()

    fun setup() {
        server.start(8080)
        val client = OkHttpClient.Builder()
            .readTimeout(1, TimeUnit.SECONDS)
            .build()
    }

    fun test_user_list_success() {
        val json = "[{\"id\":1,\"name\":\"Alice\"}]"
        server.enqueue(MockResponse()
            .setBody(json)
            .setResponseCode(200)
        )
        val result = repository.getUsers()
        assertEquals(1, result.size)
    }

    fun teardown() {
        server.shutdown()
    }
}

MockK — alternatief voor Mockito voor Kotlin met first-class ondersteuning voor coroutines, extensiefuncties en sealed classes. Stubs in MockK worden gemaakt via coEvery (voor suspend-functies) en every (voor gewone functies). In tegenstelling tot MockWebServer vervangt MockK individuele afhankelijkheidsmethoden, niet de hele HTTP-laag. Dit is handig voor unittesten van UseCase of Interactor, waar afhankelijkheden abstracties van repositories zijn.

kotlin
interface UserRepository {
    suspend fun getUsers(): List<User>
}

class GetUsersUseCaseTest {

    private val repo = mockk<UserRepository>()

    private val useCase = GetUsersUseCase(repo)

    fun test_empty_list() = runTest {
        coEvery { repo.getUsers() } returns emptyList()

        val result = useCase.invoke()

        assertTrue(result.isEmpty())
        coVerify(exactly = 1) { repo.getUsers() }
    }
}

Best practice — gebruik voor integratietests MockWebServer (onderschept echte HTTP), voor unittesten — MockK (vervangt interfaces). Vervang niet wat u niet test: als de test Repository controleert, vervang dan niet de OkHttp-client erin — gebruik echte MockWebServer op HTTP-niveau. Deze regel houdt tests relevant en vermindert breekbaarheid bij refactoring.

Implementatie van stubs op iOS met OCMock en protocollen

Swift-protocollen als stubs — in de iOS-native benadering wordt stub geïmplementeerd door het plaatsen van een teststructuur die voldoet aan het afhankelijkheidsprotocol. In plaats van de echte NetworkService krijgt de test StubNetworkService die vaste gegevens retourneert. Swift is een taal met statische typering, dus de stub moet aan hetzelfde protocol voldoen als de echte service. De compiler garandeert dat de stub alle vereiste methoden implementeert.

swift
protocol NetworkServiceProtocol {
    func fetchUsers() async throws -> [User]
}

struct StubNetworkService: NetworkServiceProtocol {
    let result: Result<[User], Error>

    func fetchUsers() async throws -> [User] {
        try result.get()
    }
}

final class UsersViewModelTests: XCTestCase {
    func test_success_state() async {
        let stub = StubNetworkService(
            result: .success([User(name: "Alice")])
        )
        let vm = UsersViewModel(service: stub)
        await vm.load()
        XCTAssertEqual(vm.users.count, 1)
    }
}

OCMock voor Objective-C — bibliotheek voor het maken van stubs en mocks in legacy iOS-projecten. OCMock ondersteunt stub-methoden met argumenten en retourwaarden. Moderne projecten in Swift geven de voorkeur aan een protocolgebaseerde aanpak met handmatige stubs — dit geeft controle over elke methode en vereist geen externe afhankelijkheden. OCMock blijft een optie voor projecten waar het protocolliseren van alle afhankelijkheden economisch niet haalbaar is.

URLProtocol voor HTTP-stubs — het systeemmechanisme van iOS voor het onderscheppen van netwerkverzoeken via een URLProtocol-subklasse. De test registreert een aangepaste URLProtocol die URLSession onderschept en stub-antwoorden retourneert. Voordeel ten opzichte van handmatige stubs: de architectuur van de applicatie hoeft niet te worden gewijzigd — URLSession blijft echt, maar gegevens worden op protocolniveau vervangen. Nadeel: moeilijker te debuggen dan een expliciete stub-service.

Veelgestelde vragen

Wat is het verschil tussen Stub en Mock?

Stub retourneert vooraf gedefinieerde gegevens en controleert niet of de aanroep heeft plaatsgevonden. Mock verifieert bovendien dat de methode met de juiste argumenten is aangeroepen (verify). Stub beantwoordt de vraag „wat terug te geven", Mock — de vraag „is er aangeroepen". Gebruik stub voor toestandscontrole, mock voor interactieverificatie.

Wanneer gebruik ik Fake in plaats van Stub?

Fake is nodig wanneer de test een werkende (zij het vereenvoudigde) implementatie vereist — bijvoorbeeld een in-memory database in plaats van Room. Stub is geschikt voor enkele scenario's met vooraf gedefinieerde gegevens. Als u dezelfde stub in 10 tests herhaalt — heeft u waarschijnlijk Fake nodig. Fake vermindert duplicatie omdat de logica in één klasse leeft.

Kunnen statische methoden worden gestubd?

Op Android — MockK voor Kotlin-objecten (object) ondersteunt mockkObject(), inclusief statische methoden van Java-klassen via mockkStatic(). Op iOS — statische Swift-methoden worden niet direct gestubd; gebruik protocollen en DI om de static-aanroep te vervangen door een instantiemethode van het protocol. Statische stubs zijn technische schuld en moeten in nieuwe code worden vermeden.

Hoe stub ik netwerkverzoeken op Android?

Gebruik MockWebServer (OkHttp) — het werkt als een lokale HTTP-server die antwoorden in de wachtrij plaatst (enqueue). Voor Retrofit is het voldoende om de basis-URL te wijzigen naar localhost:8080. Voor Ktor gebruikt u MockEngine — het ingebouwde mechanisme voor het vervangen van HttpStatement. Beide benaderingen werken zonder echt internet en geven volledige controle over de statuscode, body en headers van het antwoord.

Stub vs Spy — wat is het verschil?

Spy omhult het echte object en registreert aanroepen, terwijl Stub het object volledig vervangt door vaste antwoorden. Spy maakt gedeeltelijk gebruik van de echte implementatie mogelijk (andere methoden werken zoals voorheen), en stub niet. Als u moet controleren of een methode is aangeroepen, maar een deel van de logica moet worden uitgevoerd — gebruik spy, niet stub.

Samenvatting

  • Stub — vervangend object dat vooraf gedefinieerde antwoorden retourneert op methodeaanroepen tijdens het testen
  • Isolatie van afhankelijkheden — stubs vervangen netwerkverzoeken, databases, systeemdiensten en bestandssysteem
  • Verschil met Mock — stub verifieert geen aanroepen, het retourneert alleen gegevens zonder gedragscontrole
  • Android-gereedschappen — MockWebServer voor HTTP, MockK voor Kotlin-interfaces met coroutine-ondersteuning
  • iOS-gereedschappen — protocolgebaseerde stubs in Swift, URLProtocol voor HTTP, OCMock voor Objective-C
  • Meng geen rollen — voeg geen verify toe aan stub, gebruik mock voor aanroepverificatie
  • Stub + MockWebServer — standaardbenadering voor integratietests zonder echte server

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