What problem does Spring Cloud Contract solve, and what is a consumer-driven contract?
answer
- producer verified, consumer stubbed
- one contract → tests + WireMock stubs
- Groovy/YAML/Kotlin DSL
- stubs JAR classifier=stubs
- shared source of truth vs drifting mocks
basics
~20 sSpring Cloud Contract keeps a service (producer) and its callers (consumers) in sync. A contract is a shared file describing a request and the expected response. It generates producer tests and consumer stubs from that one file.
solid answer
~40 sSpring Cloud Contract does contract testing between an API provider (producer) and its callers (consumers) without a slow end-to-end setup. A 'contract' is a single file (Groovy DSL, YAML, or Kotlin DSL) describing an HTTP request and the expected response. From it the framework does two things: on the producer it generates tests that fail if the real controller stops honoring the contract, and it packages WireMock stubs that consumers run their tests against. 'Consumer-driven' means the contract expresses what consumers actually need, so the producer can't silently break them. It gives you the fast feedback of unit tests with confidence closer to integration tests, and both sides test against the same source of truth instead of hand-written mocks that drift.
code
groovy · 18 lines// src/test/resources/contracts/shouldReturnUser.groovy
import org.springframework.cloud.contract.spec.Contract
Contract.make {
description("should return a user by id")
request {
method GET()
url '/users/42'
}
response {
status OK() // 200
headers { contentType(applicationJson()) }
body([
id : 42,
name: 'Ada'
])
}
}go deeper
Know the one-liner: one contract file produces producer tests + consumer stubs, keeping both sides in sync.
Be able to name the DSL formats and describe the two generated artifacts and where they run.
Explain 'consumer-driven', the shared-source-of-truth benefit over hand-written mocks, and when contract testing beats E2E.
Position SCC vs OpenAPI/Pact, discuss contract ownership/governance, and where it fits in a broader test pyramid strategy.
## The problem In a microservice system, a **producer** exposes an HTTP (or messaging) API and one or more **consumers** call it. Two failure modes are common: (1) the consumer's hand-written mock of the producer drifts from reality, so consumer tests pass but production breaks; (2) the producer changes its API and unknowingly breaks a consumer. Full end-to-end tests catch this but are slow, flaky, and require every service running together. ## Contract testing Spring Cloud Contract (SCC) is Spring's implementation of **Consumer-Driven Contracts (CDC)**. A **contract** is a declarative file that pins down: an incoming **request** (method, URL, headers, body) and the **response** the producer must return (status, headers, body). Contracts are written in a **Groovy DSL**, **YAML**, or a **Kotlin DSL**, and live in the producer repository (typically `src/test/resources/contracts/...`). From that one file, SCC generates two artifacts: 1. **Producer-side generated tests.** The **Spring Cloud Contract Verifier** build plugin (Maven `spring-cloud-contract-maven-plugin` or the Gradle plugin) reads each contract at build time and code-generates a JUnit test. That test fires the contract's request at your running controller (via MockMvc/WebTestClient/RestAssured) and asserts the response matches. If your real implementation diverges from the contract, the build fails. This proves the producer actually satisfies the contract. 2. **Consumer-side stubs.** The same contract is compiled into **WireMock** stub mappings (JSON) and packaged into a **stubs JAR** (Maven classifier `stubs`). Consumers pull that JAR and run their tests against a local WireMock server serving exactly those responses — via **Stub Runner** and `@AutoConfigureStubRunner`. Because the stub is generated from the same contract the producer is tested against, consumer and producer share one source of truth. ## 'Consumer-driven' The contract ideally expresses what consumers need. In practice contracts can live in the producer repo or be contributed by consumers. The key property: the contract is verified on the producer, so a producer change that violates it fails the producer's own build. ## When to use - You own a producer with multiple internal consumers and want to catch breaking changes at build time. - You want fast, isolated tests without spinning up the whole system. Not ideal for public third-party APIs you don't control, or where OpenAPI-based tooling already governs the contract. ## Gotchas - A contract is not a schema; it's a concrete example (one request → one response), optionally with matchers for dynamic parts. - The producer test needs a **base class** to set up the controller under test; forgetting it is the most common first-time failure. - Stubs are only as good as the contracts — an untested field on the producer is invisible to consumers.
- How is a Spring Cloud Contract different from an OpenAPI/Swagger spec?OpenAPI describes the shape/schema of an API for documentation and client generation. A contract is an executable example pair (request→response) that is verified against the running producer and turned into runnable stubs, so it actively fails builds on divergence rather than just documenting.
- Does the contract file live with the producer or the consumer?Most commonly in the producer repo under src/test/resources/contracts, so the producer's build both generates its verification tests and publishes the stub JAR. Alternatively a shared external contracts repo can host them; consumers can also contribute contracts via PR to the producer.
saying these in an interview costs you the question
- Thinking the contract only documents the API and isn't actually executed/verified.
- Believing SCC spins up both services together like an end-to-end test.
- Confusing stubs (consumer side) with the generated verification tests (producer side).