I have a PubSub (message bus) implementation, whic...
# kotest
a
I have a PubSub (message bus) implementation, which has a subscribe method that accepts a callback for handling the received message. The callback is asychronously called when a message is published to the relevant topic. Is there any cleaner way of testing than the following?
Copy code
// Subscribe to the bus to capture the message
val messages = mutableListOf<MessageStaffCommand>()
messageBus.subscribe<Foo>("topics/foo/") { messages += it }

// Act
messagebus.publish("topics/foo/", fooPayload)

// Assert 
eventually(1.seconds) { messages.single() shouldBe payload }
It irks me slightly that I have to “extract” the message to a temp. variable in the callback. Of course i could assert in the callback directly but the test wouldn’t fail if something were wrong with message routing / topic mismatch, because the lambda would never be invoked.
e
If you're open to creating delegates, you could create the following utility code
Copy code
interface QueueConsumer<out T> {
    val value: List<T>
}

public inline operator fun <T> QueueConsumer<T>.getValue(
    thisRef: Any?,
    property: KProperty<*>,
): List<T> = value

inline fun <reified T> subscribingTo(topic: String): QueueConsumer<T> {
    val messages = mutableListOf<T>()
    messageBus.subscribe<T>(topic) { messages += it }
    return object : QueueConsumer<T> {
        override val value: List<T>
            get() = messages
    }
}
Then from your test
Copy code
// Subscribe to the bus to capture the message
val messages by subscribingTo("topics/foo/")

// Act
messagebus.publish("topics/foo/", fooPayload)

// Assert 
eventually(1.seconds) { messages.single() shouldBe payload }
Haven't tried it out really so can't promise it'll work flawlessly. 🙂
a
thanks, good idea 👍