Run assertions with an argument
There are some special argument matchers that can only be used when verifying that a mocked function was called. withArg
and its variants allow you to capture an argument and run your own assertions on it without the need to set up a capturing slot.
data class File(
val name: String,
val data: ByteArray
)
interface FileNetwork {
fun download(name: String): File
fun upload(file: File)
}
When using a capturing slot, testing the FileNetwork.download
function looks like this:
val network = mockk<FileNetwork>()
val slot = slot<String>()
every { network.download(capture(slot)) } returns mockk()
network.download("testfile")
verify {
network.download(any())
}
assertTrue("testfile" == slot.captured)
withArg
simplifies this code so no slot is needed.
val network = mockk<FileNetwork>()
every { network.download(any()) } returns mockk()
network.download("testfile")
verify {
network.download(withArg {
assertTrue("testfile" == it)
})
}
Arrays and data classes
withArg
can be helpful when you use arguments that aren’t easily compared, such as a data class containing arrays. The equals()
function on an array works differently than on a List
. Arrays are only equal if you compare with the exact same instance, while lists are equal if all of their items are equal. Since Kotlin data classes use the equals()
function with each property, this array behaviour affects them.
val expected = File("hello", data = "world".toByteArray())
network.upload(File("hello", data = "world".toByteArray()))
// fails because the Files are not equal
verify {
network.upload(expected)
}
In your test, you can choose to compare properties individually using withArg
.
val expected = File("hello", data = "world".toByteArray())
network.upload(File("hello", data = "world".toByteArray()))
verify {
network.upload(withArg {
assertTrue(expected.name == it.name)
assertTrue(expected.data contentEquals it.data)
})
}
Nullable arguments
withNullableArg
is also provided by MockK when you wish to use it with a nullable argument.
Coroutines
MockK provides variants with withArg
and withNullableArg
that allow coroutine code to be executed. These variants are coWithArg
and coWithNullableArg
. If your assertions call a suspend function, these variants should be used.