'Mockito - verify call on a matched parameter
I have the following scenario. Code I'm testing (kotlin/JVM/Spring Boot)
private val client: WebClient, // injected by Spring Boot.
// (...)
client.post()
.uri(uri)
.body(BodyInserters.fromFormData("query", query))
.header(CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED.toString())
// (...)
client
is a WebClient
.
In my testing code I want to check that the client
is called with uri and query matching an arbitrary predicate. I came up with this:
@MockBean private val hgWebClient: WebClient, // injected by Spring Boot Test.
// (...)
fun mockPostResponse(
bodyMatch: (String) -> Boolean, // in Java it would be Predicate<String>
uriMatch: (URI) -> Boolean,
response: String
): WebClient.RequestBodyUriSpec {
val uriReceiver: WebClient.RequestBodyUriSpec = mock()
// in Java it would be "when"
whenever(hgWebClient.post()).thenReturn(uriReceiver)
val bodyReceiver: WebClient.RequestBodyUriSpec = mock()
// here matching with argThat works just fine
whenever(uriReceiver.uri(argThat<URI>(uriMatch))).thenReturn(bodyReceiver)
val spec3: WebClient.RequestBodyUriSpec = mock()
// here I have to use "any" because
// .body(BodyInserters.fromFormData("query", argThat(bodyMatch))) won't work
whenever(bodyReceiver.body(any<BodyInserters.FormInserter<String>>())).thenReturn(spec3)
val spec4: WebClient.RequestBodyUriSpec = mock()
whenever(spec3.header(any(), any())).thenReturn(spec4)
whenever(
spec4.exchangeToMono(any<Function<ClientResponse, Mono<String>>>())
).thenAnswer {
Mono.fromSupplier { mockHttpResponse(response) }
}
// return both bodyReceiver and uriReceiver
}
Later I want to verify that these methods were called, so
mockPostResponse(...)
// works just fine
verify(receivers.uriReceiver) { 1 * { this.uri(argThat(uriMatch)) } }
// No idea what to put there so it verifies that "query" in BodyInserters.fromFormData("query", query)
// matches the "bodyMatch" predicate
verify(receivers.bodyReceiver) { 1 * { this.body(???) } }
To sum up, the specific problem is that I don't know how to mock a method call which argument itself is a mock, on which I verify that a call to a static function was made (or I'm missing something obvious). I think it's something with BodyInserters.fromFormData
being a static function (?).
How to properly mock this scenario and actually verify that arguments match predicates?
Solution 1:[1]
I've found a workaround, which isn't that bad
Create a wrapper around the static Spring Boot factory and inject that in real code.
/**
* Wrapper around BodyInserters static factory
*/
@Service
class BodyInsertersFactory {
fun fromFormData(name: String, value: String): BodyInserters.FormInserter<String> =
BodyInserters.fromFormData(name, value)
}
Then in tests:
@SpyBean private val bodyInsertersFactory: BodyInsertersFactory,
// (...)
verify(bodyInsertersFactory) { 1 * { fromFormData(any(), argThat(bodyMatch)) } }
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Lutos?aw |