You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Cloud Contract能否为WebFlux响应式Flux API编写契约?

Can You Write Contracts for This Reactive Flux API?

Absolutely! Spring Cloud Contract fully supports reactive WebFlux endpoints, including those that consume and produce Flux streams. The main difference from standard REST endpoints is that you need to explicitly mark the contract as handling asynchronous/streaming responses, which tells SCC to generate stubs and tests that work with non-blocking data flows.

Adapting Your Contract for Flux Input/Output

To define a contract for your /endlessecho endpoint, you’ll use SCC’s Groovy DSL (or YAML, if you prefer) and add the async() marker to the response section to indicate it’s a streaming endpoint. Here’s a sample contract file (src/test/resources/contracts/endlessEcho.groovy):

org.springframework.cloud.contract.spec.Contract.make {
    description "Echoes back each string from the input Flux stream"
    request {
        method POST()
        url "/endlessecho"
        headers {
            contentType applicationJsonStream() // Use textPlain() if your API uses plain text streams
        }
        body([
            "hello",
            "world",
            "spring-cloud"
        ])
        bodyMatchers {
            jsonPath('$', byType()) // Validates the input is an array of strings, order preserved
        }
    }
    response {
        status OK()
        headers {
            contentType applicationJsonStream() // Match your API's response content type
        }
        body([
            "hello",
            "world",
            "spring-cloud"
        ])
        bodyMatchers {
            jsonPath('$', byType())
        }
        async() // Critical: Marks this as a streaming/async response
    }
}

A few key notes here:

  • Use applicationJsonStream() (or textPlain()/textEventStream()) to match the content type your API uses for streaming. If your endpoint accepts plain text instead of JSON, swap out the content type and adjust the body to raw strings instead of a JSON array.
  • The async() flag is non-negotiable—it tells SCC that this isn’t a single-response endpoint, so generated tests and stubs will handle the streaming behavior correctly.
WireMock Compatibility

Yes, WireMock works seamlessly with these contracts! SCC will generate WireMock stubs that simulate the streaming response behavior. WireMock 2.27+ has native support for streaming responses, so make sure you’re using a recent enough version.

The generated stub will listen for POST requests to /endlessecho with the expected streaming input, and respond with a matching stream of data—just like your actual WebFlux endpoint does.

Testing the Contract

When you generate tests from the contract (using SCC’s test generation plugin), it will create a test that uses WebTestClient to send a Flux request and validate the streaming response. You can also write your own manual test like this to verify:

@Autowired
private WebTestClient webTestClient;

@Test
void endlessEcho_shouldEchoInputStream() {
    webTestClient.post().uri("/endlessecho")
        .contentType(MediaType.APPLICATION_JSON_STREAM)
        .body(Flux.just("hello", "world", "spring-cloud"), String.class)
        .exchange()
        .expectStatus().isOk()
        .expectBodyList(String.class)
        .containsExactly("hello", "world", "spring-cloud");
}
Final Tips
  • Ensure your project’s SCC configuration enables WebFlux support. For Spring Boot 3+, this is often enabled by default if you have spring-boot-starter-webflux on the classpath, but you can explicitly set spring.cloud.contract.webflux.enabled=true in your application.properties to be safe.
  • If you’re using Gradle or Maven, double-check that you’ve applied the Spring Cloud Contract plugin correctly (e.g., org.springframework.cloud.contract plugin for Gradle) to generate stubs and tests.

内容的提问来源于stack exchange,提问作者Kristof

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:29:54