Skip to content

WebTestClient leaks when ParameterizedTypeReference is used #33389

@MFAshby

Description

@MFAshby

WebTestClient has a special case when a Void response is expected. Method WebTestClient.ResponseSpec#returnResult(java.lang.Class<T>) has this documentation comment:

Note that when {@code Void.class} is passed in, the response body is consumed and released.

The same special case logic is not applied to the overloaded version of this method: WebTestClient.ResponseSpec#returnResult(ParameterizedTypeReference<T>). This is a bit unexpected; and caused a memory leak in my tests when I swapped a Class parameter for a ParameterizedTypeReference parameter. The following sample code shows the problem (additional GC is forced to make the leak happen faster; netty's leak detection happens on GC):

import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.test.web.reactive.server.WebTestClient; import reactor.netty.http.client.HttpClient; class Scratch { public static void main(String[] args) throws Exception { var client = WebTestClient.bindToServer(new ReactorClientHttpConnector(HttpClient.create())) .build(); var b = client.get().uri("http://localhost:8000"); long count = 0; while(true) { count += 1; if (count % 10000 == 0) { System.out.printf("Done %d requests forcing a G\n", count); System.gc(); } b.exchange() .expectStatus().isEqualTo(200) //.returnResult(Void.class); // <-- doesn't leak .returnResult(ParameterizedTypeReference.forType(Void.class)); // <-- leaks } } }

The workaround is to use the Class signature, or consume the response body some other way using e.g. by specifying .consumeWith(...).

Metadata

Metadata

Assignees

Labels

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

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions