Home > other >  How to mock a Class<T> Generics object in webclient bodyToMono method
How to mock a Class<T> Generics object in webclient bodyToMono method

Time:01-01

I want to mock this webclient post call. Service

fun <T : Any> post(uri: String, body: Any, responseType: Class<T>): Class<T>? {
    return webClient.post()
        .uri(uri)
        .bodyValue(body)
        .retrieve()
        .bodyToMono(responseType::class.java)
        .block()
}

I am getting a null pointer exception when I am mocking bodyToMono using a Class<T> generic.

ServiceTest


@Mock
lateinit var mockWebClient: WebClient

@Autowired
private lateinit var onelinkRestClient: OnelinkRestClient

@Mock
private lateinit var requestHeadersMock: WebClient.RequestBodyUriSpec

@Mock
private lateinit var responseMock: WebClient.ResponseSpec

@Mock
private lateinit var requestBodyUriMock: WebClient.RequestBodyUriSpec

@Mock
private lateinit var requestBodyMock: WebClient.RequestBodySpec

@BeforeEach
fun setUp() {
    webclient = Service(mockWebClient)
}

val uri = "/path"

`when`(mockWebClient.post()).thenReturn(requestBodyUriMock)
`when`(requestBodyUriMock.uri(uri)).thenReturn(requestBodyMock)
`when`(requestBodyMock.bodyValue((requestDTO))).thenReturn(requestHeadersMock)
`when`(requestHeadersMock.retrieve()).thenReturn(responseMock)
`when`(responseMock.bodyToMono(ResponseDTO::class.java)).thenReturn(Mono.just(responseDTO))
val response = webclient.post<ResponseDTO>("/path", responseDTO, responseDTO::class.java)

When running serviceTest, it gives me an error:

java.lang.NullPointerException: Cannot invoke "reactor.core.publisher.Mono.block()" because the return value of "org.springframework.web.reactive.function.client.WebClient$ResponseSpec.bodyToMono(java.lang.Class)" is null

If I change it from generic Class<T> to a some Class defined it doesn't throw NPE


fun <T : Any> post(uri: String, body: Any, responseType: Class<T>): Class<T>? {
    return webClient.post()
        .uri(uri)
        .bodyValue(body)
        .retrieve()
        .bodyToMono(responseType::class.java)
        .block()
}
     

Insted of bodyToMono of responseType::class.java, when I do it with defined class, the testcase passes.

eg

.bodyToMono(abc::class.java)

I am trying to mock a generic class of type T Class<T> in bodyToMono.

CodePudding user response:

I think your test is correct, but your function is wrong. It calls ::class on a Class instance, so you will always end up with a Class<Class<?>>.

Don't you want the following?

.bodyToMono(responseType)

or perhaps:

.bodyToMono(responseType.java)

(I don't know Kotlin well enough)

  • Related