Skip to content

RestClient Unit Test with @RestClientTest and MockRestServiceServer fails when using request factory JdkClientHttpRequestFactory #38832

Open
@williamsuane

Description

@williamsuane

Description

When creating RestClient Bean with JdkClientHttpRequestFactory, like below

@Bean
  public RestClient restClient(RestClient.Builder builder) {
    return builder
        .requestFactory(new JdkClientHttpRequestFactory()) 
        .baseUrl(<baseUrl>)
        .build();
  }

Tests using @RestClientTest and MockRestServiceServer fail to connect.

Sample Application

https://github.com/williamsuane/failing-cat-fact/tree/master

Just execute the following test, as is

@RestClientTest({CatFactService.class})
class CatFactServiceTest {

  @Autowired
  private MockRestServiceServer server;
  @Autowired
  private CatFactService catFactService;

  @Test
  void test() {
    server.expect(MockRestRequestMatchers.requestTo("http://localhost:8080/fact"))
        .andRespond(MockRestResponseCreators.withSuccess("""
            	{"fact":"In 1987 cats overtook dogs as the number one pet in America."}
            """, MediaType.APPLICATION_JSON));

    var catFact = catFactService.getFact();
    assertEquals("In 1987 cats overtook dogs as the number one pet in America.", catFact.fact());
  }
}

it blows with the following exception

org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://localhost:8080/fact": null

	at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.createResourceAccessException(DefaultRestClient.java:534)
	at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchangeInternal(DefaultRestClient.java:459)
	at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.retrieve(DefaultRestClient.java:424)
	at com.example.demo.CatFactService.getFact(CatFactService.java:17)
	at com.example.demo.CatFactServiceTest.test(CatFactServiceTest.java:28)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: java.net.ConnectException
	at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:951)
	at java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:133)
	at org.springframework.http.client.JdkClientHttpRequest.executeInternal(JdkClientHttpRequest.java:94)
	at org.springframework.http.client.AbstractStreamingClientHttpRequest.executeInternal(AbstractStreamingClientHttpRequest.java:70)
	at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66)
	at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchangeInternal(DefaultRestClient.java:453)
	... 6 more
Caused by: java.net.ConnectException
	at java.net.http/jdk.internal.net.http.common.Utils.toConnectException(Utils.java:1028)
	at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:227)
	at java.net.http/jdk.internal.net.http.PlainHttpConnection.checkRetryConnect(PlainHttpConnection.java:280)
	at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$2(PlainHttpConnection.java:238)
	at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934)
	at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911)
	at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
	at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1773)
	at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.nio.channels.ClosedChannelException
	at java.base/sun.nio.ch.SocketChannelImpl.ensureOpen(SocketChannelImpl.java:202)
	at java.base/sun.nio.ch.SocketChannelImpl.beginConnect(SocketChannelImpl.java:786)
	at java.base/sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:874)
	at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$1(PlainHttpConnection.java:210)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:571)
	at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:212)
	... 10 more

By removing the .requestFactory(new JdkClientHttpRequestFactory()) from

@Bean
  public RestClient restClient(RestClient.Builder builder) {
    return builder
        .baseUrl(<baseUrl>)
        .build();
  }

The test works perfectly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions