Skip to content

view testing

Florian Schuster edited this page Mar 23, 2025 · 14 revisions

a consumer or view that binds its ui to a controller, can be tested by accessing the Controller.toStub(). once accessed, the Controller is stubbed and cannot be un-stubbed.

when stubbed, Controller.mutate() and Controller.reduce() are not executed.

  • use ControllerStub.dispatchedActions : List<Action> to verify if view bindings trigger the correct actions
  • use ControllerStub.emitState(State) to verify if Controller.state is correctly bound to a view
@Test
fun valueButtonClickTriggersCorrectAction() {
    // given
    val controller = //create ValueController
    val view = ViewScreen(controller.apply { toStub() })
    
    // when
    onNodeWithTag("setValueButton").performClick()
    
    // then
    assertEquals(
        Action.SetValue(value = 3), 
        controller.stub().dispatchedActions.last()
    )
}

@Test
fun stubbedStateUpdatesTextViewText() {
    // given
    val expectedValue = 42
    val controller = //create ValueController
    val view = ViewScreen(controller.apply { toStub() })
    
    // when
    controller.stub.emitState(State(counterValue = expectedValue))
    
    // then
    onNodeWithTag("valueTextView").assertTextEquals("$testValue")
}

TestOnlyStub Annotation

TestOnlyStub is an annotation that marks the toStub extension function to remind users to not use it in production.

In tests, either suppress the annotation per test/class/file or suppress it for the whole test target.

compilerOptions {
    optIn.add("at.florianschuster.control.TestOnlyStub")
}

example

Clone this wiki locally