oolong-kt/oolong

Unit Test Documentation

Opened this issue ยท 3 comments

Is there any way to unit test update ? If there's a way, is there any documentation ? Thank you

Testing init, update, and view is as simple as calling those functions and asserting on the result. There's nothing to help with effect testing in the library yet, however, it might eventually look something like this:

class EffectAsserter<Msg : Any> {

    private val calls: MutableList<Msg> = mutableListOf()
    private val dispatch: Dispatch<Msg> = { msg -> calls.add(msg) }

    fun run(effect: Effect<Msg>) =
        apply { runBlocking { effect(dispatch) } }

    fun assertEquals(msgs: Iterable<Msg>) =
        apply { assertEquals(msgs, calls) }

    fun assertCount(count: Int) =
        apply { assertEquals(count, calls.size) }

}

@Test
fun `effect test`() {
    val (_, effect) = update(msg, model)
    EffectAsserter<Msg>()
        .run(effect)
        .assertCount(1)
        .assertEquals(listOf(Msg.Foo))
}

I've added this issue to the Documentation Project.

Personally I create the following simple helpers:

fun <Msg> Effect<Msg>.asFlow(): Flow<Msg> =
    channelFlow<Msg> { this@asFlow { sendBlocking(it) } }

suspend fun <Msg> Effect<Msg>.perform(): List<Msg> =
    asFlow().toList()

And then in my tests I use it like this:

val (_, effect) = update(msg, model)

// Perform the effect and return the list of dispatched messages
val messages: List<Msg> = runBLocking { effect.perform() }

// assert using my favoring assertion library
messages.shouldBeEmpty()

Follow up: I would recommend using TestCoroutineDispatcher so you can advance time like this https://github.com/oolong-kt/oolong/blob/main/oolong/src/jvmTest/kotlin/oolong/effect/EffectTest.kt#L48