mockk: Message from Assertk assertions is not printed when using withArg block.
Prerequisites
Please answer the following questions for yourself before submitting an issue.
- I am running the latest version
- I checked the documentation and found no answer
- I checked to make sure that this issue has not already been filed
Expected Behavior
The message from AssertionFailedError (which is thrown by Assertk lib) should be printed when assertion is performed in withArg block.
Current Behavior
The message from AssertionFailedError (which is thrown by Assertk lib) exception is not printed when the checking is performed in withArg block.
Context
Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.
- MockK version: 1.11.0
- OS: macOS Big Sur
- Kotlin version: 1.5
- JDK version: 11
- JUnit version: 5
- Type of test: unit test
Minimal reproducible code (the gist of this issue)
// -----------------------[ GRADLE DEFINITIONS ] -----------------------
project.ext.versions = [
junit : '5.7.2',
assertk : '0.24',
mockk : '1.11.0'
]
dependencies {
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: versions.junit
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: versions.junit
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: versions.junit
testImplementation group: 'com.willowtreeapps.assertk', name: 'assertk-jvm', version: versions.assertk
testImplementation group: 'io.mockk', name: 'mockk', version: versions.mockk
}
// -----------------------[ YOUR CODE STARTS HERE ] -----------------------
package some.example.com
import io.mockk.every
import io.mockk.mockk
import org.apache.kafka.common.KafkaFuture
import kotlin.test.Test
class SomeExampleTest {
val orderRepository: OrderRepository = mockk()
val orderService: OrderService = OrderService(orderRepository)
@Test
fun test() {
// given
thereIsOrder(anOrder())
// when
orderService.pay(anOrderPayment())
// then
wasSaved(anOrder())
}
fun wasSaved(order: Order, times: Int = 1) {
verify(exactly = times) {
orderRepository.save(withArg{ equalsTo(order) })
}
}
private fun MockKAssertScope.equalsTo(order: Order) {
assertThat(this.actual as Order)
.hasCommandId(order.commandId)
.hasOrderId(order.orderId)
// and so on
}
// walk around
private fun MockKAssertScope.equalsToAndLog(order: Order) {
try {
assertThat(this.actual as Order)
.hasCommandId(order.commandId)
.hasOrderId(order.orderId)
// and so on
} catch (t: Throwable) {
logger.error(t) {}
throw t
}
}
}
// -----------------------[ YOUR CODE ENDS HERE ] -----------------------
I found that exception is catched here, and the stacktrace is not logged.
package io.mockk
data class FunctionMatcher<in T : Any>(
val matchingFunc: (T) -> Boolean,
override val argumentType: KClass<*>
) : Matcher<T>, TypedMatcher, EquivalentMatcher {
override fun equivalent(): Matcher<Any> = ConstantMatcher(true)
override fun match(arg: T?): Boolean {
return if(arg == null) {
false
} else {
try {
matchingFunc(arg)
} catch (a: AssertionError) {
false
}
}
}
override fun toString(): String = "matcher<${argumentType.simpleName}>()"
}
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 1
- Comments: 23 (13 by maintainers)
Is there any update on this? Or is the only way to make it work to use a capture? Having no messages is especially cumbersome when using recursive AssertJ statements inside a
withArg
block.We may need to revert this change. One unintended consequence is that in cases when multiple calls are made to the same mock, this will fail when matching the first one…
Test that succeeded before 12.3.1:
now fails…
One workaround with slot() for common situations that is a little more concise and also scoped is the following:
Meanwhile, you can obviously build your own snapshot from master 😃
I usually do releases manually once there are enough new changes.
I already did some changes to add support for Kotlin 1.6.* and remove support for 1.3.*, so I may actually make a release pretty soon.
It’s not just a matter of muddying waters, it’s really that matchers are meant for matching parameters, not to execute code, and thus they live in a module where there is neither logging enabled or actually any other dependencies.
Adding a logging dependency just for this case seems really overkill to me, given that there is a better, clearer way to achieve the same behavior.