首页 > 解决方案 > Spring 的 WebClient 使用 MockServer 挂在 bodyToMono(Pojo) 上

问题描述

我想模拟一个外部 API,我将其作为服务的一部分进行调用。因此,我想使用MockWebServer来自 okhttp3 的。我的问题是调用bodyToMono工作正常,如果我想将正文作为字符串检索,但在将其作为数据类检索时不起作用。我尝试使用以下代码片段对其进行修剪:

public class MockWebClientTest {

    private MockWebServer server;

    @BeforeEach
    public void setUp() throws IOException {
        server = new MockWebServer();
        server.start(9876);
    }

    @AfterEach
    public void tearDown() throws IOException {
        server.shutdown();
    }

    @Test
    public void stringWorks() throws JsonProcessingException {
        createMockedTokenCall();

        Mono<String> response = WebClient.create(this.server.url("/").toString())
            .get()
            .uri("/")
            .retrieve()
            .bodyToMono(String.class);

        System.out.println(response.block());
    }

    @Test
    public void classDoesNotWork() {
        createMockedTokenCall();

        Mono<AuthToken> response = WebClient.create(this.server.url("/").toString())
            .get()
            .uri("/")
            .retrieve()
            .bodyToMono(AuthToken.class);

        System.out.println(response.block());
    }

    private void createMockedTokenCall() {
        server.enqueue(new MockResponse().setBody("{\"accessToken\":\"BARBAR\",\"refreshToken\":\"FOOFOO\"}"));
    }
}

class AuthToken {
    private String accessToken;
    private String refreshToken;

    //constructor
}

第一个 Test ( stringWorks) 工作正常并返回正确的 json 表示。但是,第二个测试 ( ) 在通话中classDoesNotWork永远挂起。bodyToMono

我的猜测是它与 okttp3 库直接无关,因为我在使用 Wiremock 时遇到了同样的错误。然而,当以真正的 API 端点为目标时,相同的代码也可以工作。不幸的是,我找不到另一种方法来测试我的调用,WebClient因为 Spring 目前没有直接的模拟支持(参见SPR-15286)。

我真的很期待在这件事上提供帮助!提前致谢!

一般评论:这基本上是https://github.com/spring-projects/spring-framework/blob/master/spring-webflux/src/test/java/org/springframework/webshouldReceiveJsonAsPojo中测试用例的或多或少的副本/reactive/function/client/WebClientIntegrationTests.java

标签: javaspringokhttp3spring-webflux

解决方案


好的,在查看了链接的测试并进行了一些比较之后,我找到了解决方案(或者可以说是我的错误):我忘记了正确的Content-Type标题。所以它使用以下方法工作:

private void createMockedTokenCall() {
    server.enqueue(new MockResponse().setHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE).setBody("{\"accessToken\":\"BARBAR\",\"refreshToken\":\"FOOFOO\"}"));
}

除了我犯了一个错误,我真的认为这不应该导致应用程序无限挂起......


推荐阅读