Mockito - 验证对匹配参数的调用



我有以下情况。我正在测试的代码(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是一个WebClient.

在我的测试代码中,我想检查client是否使用 uri 和查询匹配任意谓词进行调用。我想出了这个:

@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
}

稍后我想验证是否调用了这些方法,因此

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(???) }  }

综上所述,具体问题是我不知道如何模拟参数本身就是模拟的方法调用,我验证是否调用了静态函数(或者我错过了一些明显的东西)。我认为这是BodyInserters.fromFormData静态函数(?

如何正确模拟此场景并实际验证参数是否与谓词匹配?

我找到了一个解决方法,还不错

在静态 Spring Boot 工厂周围创建一个包装器,并将其注入实际代码中。

/**
* Wrapper around BodyInserters static factory
*/
@Service
class BodyInsertersFactory {
fun fromFormData(name: String, value: String): BodyInserters.FormInserter<String> =
BodyInserters.fromFormData(name, value)
}

然后在测试中:

@SpyBean private val bodyInsertersFactory: BodyInsertersFactory,
// (...)
verify(bodyInsertersFactory) { 1 * { fromFormData(any(), argThat(bodyMatch)) } }

相关内容

最新更新