I’m building a prototype for a new application using Spring Webflux and Kotlin. Spring Webflux contains a WebTestClient for unit tests. According to the documentation I should be able to test the results of a REST call like this:
@Test
fun getVersion_SingleResult_ContentTypeJson_StatusCodeOk_ContentEqualsVersion() {
//given
val version = Version("Test", "1.0")
val handler = ApiHandler(version)
val client = WebTestClient.bindToRouterFunction(ApiRoutes(handler).apiRouter()).build()
//expect
val response = client.get().uri("/api/version/").exchange()
response.expectStatus().isOk
response.expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8)
response.expectBody(Version::class.java).isEqualTo(version)
}
However, I’m running into some type interference issues. The problem is in the combination of ‘expectBody’ and ‘isEqualTo’.
The error I get is:
Kotlin: Type inference failed: Not enough information to infer parameter T in fun isEqualTo(p0: Version!): T! Please specify it explicitly.
The used methods from the Spring Webflux framework have the following signatures:
<B> WebTestClient.BodySpec<B, ?> expectBody(Class<B> var1);
public interface BodySpec<B, S extends WebTestClient.BodySpec<B, S>> {
<T extends S> T isEqualTo(B var1);
}
The code does compile when I call the isEqualTo method if I specify the function generic as <Nothing>
(ie: isEqualTo<Nothing>(version)
, however this leads to a NullPointer exception even if the body of the response has a value.
I’m not sure how I could fix this. The combination of the wildcard in the expectBody and the circular generic in the BodySpec has me puzzled.
Well, got an update. Also asked it on Stack Overflow and a member of the Spring engineering team jumped in to explain that this is a known issue (See JIRA: Kotlin unable to inherit type for WebTestClient#BodySpec [SPR-15692] · Issue #20251 · spring-projects/spring-framework · GitHub)