Skip to content

Kotlin unable to inherit type for WebTestClient#BodySpec [SPR-15692] #20251

Closed
@spring-projects-issues

Description

@spring-projects-issues

Mikhail Konovalov opened SPR-15692 and commented

It seems that due to recursive generics in BodySpec interface

interface BodySpec<B, S extends BodySpec<B, S>>

and due to expectBody method returns

<B> BodySpec<B, ?> expectBody(Class<B> bodyType);

WebTestClient cannot be used in Kotlin.

Kotlin inherits the result of .expectBody(Person::class.java) as BodySpec<Person, *> and thus the following methods in chain cannot be constructed due to the following error:

Error:(25, 20) Kotlin: Type inference failed: Not enough information to infer parameter T in fun <T : Nothing!> isEqualTo(p0: Controller.Person!): T!
Please specify it explicitly.

And it applies only Nothing as a type parameter.
But in this case generated bytecode contains the following line

throw null

Example:

@Test
fun `test get`() {
    val expectBody: BodySpec<Person, *> = client.get().uri("/person/42").exchange()
            .expectBody(Person::class.java)
    expectBody.isEqualTo(Person("42", "Ivan"))                            // doesn't compile here
    expectBody.isEqualTo<BodySpec<Person, *>>(Person("42", "Ivan"))       // doesn't compile here
    expectBody.isEqualTo<Nothing>(Person("42", "Ivan"))                   // compile but lead to "throw null" in bytecode
}

If you work with list the situation is a bit better - Kotlin still cannot inherit type param automatically but you can specify it explicitly due to method expectBodyList in interface ListBodySpec doesn't return wildcards

<E> ListBodySpec<E> expectBodyList(Class<E> elementType);

Example:

@Test
    fun `test list`() {
        val expectBodyList: ListBodySpec<Person> = client.get().uri("/person").exchange()
                .expectBodyList(Person::class.java)
        expectBodyList.consumeWith<ListBodySpec<Person>> { list -> Assert.assertTrue(true) }   // need to specify type param explicitly
    }

Full example with java and kotlin can be found here.
Tests in java works well in these cases.


Affects: 5.0 RC2

Reference URL: https://gist.github.com/mskonovalov/42761bbc548e92c2af16c40cffcfcaf3

Issue Links:

Referenced from: commits 91c8b62, 568a0b5

0 votes, 5 watchers

Metadata

Metadata

Assignees

Labels

in: testIssues in the test modulein: webIssues in web modules (web, webmvc, webflux, websocket)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions