Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type interference issue with the WebFlux WebTestClient and Kotlin

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
    var 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 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);
}

Sadly I'm running into the limits of my knowledge of generics and the differences between Kotlin and Java which means that I'm not sure how I should specify this.

Edit: Like I said below, it compiles when I use isEqualTo<Nothing>(version). However, this causes a NullPointerException when the isEqualTo ends without a failure. This seems to be because the 'isEqualTo' method returns a value, which is now defined as the 'Nothing' type.

like image 975
Velde Avatar asked Jul 25 '17 06:07

Velde


2 Answers

This is now fixed on Kotlin side, see this blog post for more details. Require a flag with Kotlin 1.5.30 and will be the default as of Kotlin 1.6.0.

like image 121
Sébastien Deleuze Avatar answered Nov 16 '22 00:11

Sébastien Deleuze


I ran into the same issue.

Looks like the solution is to use an extension function .expectBody<Version>()

please refer to: https://github.com/spring-projects/spring-framework/issues/20251#issuecomment-453457296

so, you can change your code to:

import org.springframework.test.web.reactive.server.expectBody
......
response<Version>.expectBody().isEqualTo(version)

it should work

like image 1
Li Ying Avatar answered Nov 16 '22 00:11

Li Ying