During Pact message provider verification, how is the named message produced, and why is no real destination involved?
answer
- Nothing is published, so something is called
- The description is the lookup key
- Two hooks: state handler and message producer
- In-process target, not an HTTP target
- Return the real emitter's output, not a fixture
basics
~20 sThe verifier calls a provider-side method registered under the interaction's description, which builds and returns the payload the service would emit, and compares it with the recorded matchers. Nothing is published, so no broker or topic is needed.
solid answer
~40 sVerification is configured with a **message target** instead of an HTTP target. For each recorded interaction the verifier finds a provider method registered against that interaction's **description** — in Pact-JVM, an annotation carrying the description string — runs any state handler for the named provider states first, then calls the method and compares the returned payload and metadata against the recorded contents and matching rules. Because the message is produced on demand and in-process, the build needs no broker, no destination and no credentials, and runs in unit-test time. The catch is that the method can return anything: if it returns a hand-written fixture rather than calling the real emitter, verification proves two fixtures agree. Wire it to the production emitter path.
code
java · 25 lines@Provider("donation-scheduler")
@PactBroker
class SlotBookedProviderTest {
@BeforeEach
void useMessageTarget(PactVerificationContext context) {
context.setTarget(new MessageTestTarget());
}
@TestTemplate
@ExtendWith(PactVerificationInvocationContextProvider.class)
void verify(PactVerificationContext context) {
context.verifyInteraction();
}
@State("donor 40817 has a confirmed slot")
void donorHasConfirmedSlot() {
bookings.save(new Booking("40817", "BR-217"));
}
@PactVerifyProvider("a slot-booked event for donor 40817")
String slotBooked() {
return eventPublisher.buildSlotBookedPayload("40817");
}
}go deeper
Recall that the producer side of a message contract is checked on the producer's own build, in memory, without any broker being started.
Be able to describe the two hooks and their lookup keys: a state handler keyed by the provider state name, and a message-producing method keyed by the interaction description.
An interviewer expects you to spot the fixture trap unprompted — a verification method that does not call production emitter code cannot fail — and to say how you review for it.
Own the standard across services: which production seam every verification method must call, how interaction descriptions are renamed safely, and how you keep a large verification suite meaningful rather than merely green.
## The verifier has no event to catch, so it asks for one Provider verification of an HTTP pact is easy to picture: the verifier sends the recorded request to a running provider and compares the response. For an asynchronous message there is no request to send and no response to catch. Waiting for the producer to emit something onto a real destination would make the build slow, flaky and dependent on infrastructure — exactly what contract testing exists to avoid. So Pact inverts it. The verification run is configured with a **message target** rather than an HTTP target, and for each recorded interaction the verifier looks up a provider-side method **registered under that interaction's description**. In Pact-JVM that registration is an annotation carrying the description string; the method builds and returns the payload the service would emit. The verifier then compares that returned payload — and, where supported, its metadata — against the recorded contents and matching rules. Two consequences follow immediately: - **The description is a coupling point.** It is not documentation; it is the lookup key. Rename it on the consumer side and the provider's verification fails to find a producer method for it. - **The message is produced on demand, in-process.** Nothing is published, nothing is consumed, and the build needs no broker, no topic and no credentials. ## Provider states on the message side A recorded message may name provider states. On the provider these are wired the same way as for HTTP: a state-handler method is registered against the state name, the verifier runs it before the interaction, and it seeds whatever data the emitter will read. The distinction worth making out loud is that the state handler prepares the *world* the emitter reads from, while the description-registered method produces the *message* — two different hooks with two different lookup keys, and confusing them is a common source of "no provider method found" failures. | | HTTP interaction | Asynchronous message interaction | | --- | --- | --- | | Verifier target | the running provider over HTTP | an in-process message target | | How the actual is obtained | replay the recorded request | call the method registered for the description | | Lookup key | request path and method | the interaction description string | | Infrastructure needed | provider process listening | none | | Compared | status, headers, response body | returned payload and metadata | ## The fixture trap Because the producer method can return anything, it is trivially easy to make verification pass by returning a hand-written JSON string that happens to match the pact. That verifies that two fixtures agree and nothing else. The whole value of the exercise depends on that method calling the **real emitter path**: the same factory, mapper or serializer the production publisher uses, given domain input seeded by the state handler. A useful review question for any message verification is "which production class does this call?" — if the answer is "none", the test is theatre. The same logic applies to the payload's outer form. If production serializes through a codec, and the verification method returns a JSON string produced by a different route, a codec change will pass verification and break consumers. ## Producer-first equivalent Spring Cloud Contract takes the other route: the message contract declares a trigger and the output message, and the plugin generates a provider test that invokes the trigger and captures the message from a test-scoped messaging abstraction rather than a real broker. The mechanism differs, the principle is identical — the producer's own code is invoked, and the transport is stubbed out. ## Making it real in a fan-out A blood-donation scheduling service with 9 consuming services is verified against every pact its consumers publish. Its verification build runs 23 message interactions in a few seconds, none of which touch a broker, because each is a method call. When a refactor changed the emitter's date formatting, 4 of those 23 failed on the provider's own build — before the change was published. That failure mode is exactly what the on-demand model buys, and it only worked because the verification methods called the real emitter. ## What to say when asked State the mechanism first — the verifier calls a provider method registered under the interaction's description, and compares what it returns — then explain that this is what removes the broker from the loop. Finish with the fixture trap, because it is the difference between a verification suite that catches producer regressions and one that cannot fail.
- A consumer renames the interaction description. What breaks on the provider build?The verifier can no longer find a provider method registered for the new description, so that interaction fails with a missing-producer error rather than a payload mismatch. The description is a lookup key, not a comment, which is why teams treat it as part of the contract and rename it deliberately on both sides.
- How do you tell a genuine message verification from one that cannot fail?Follow the call. If the method registered for the description calls the production emitter, mapper or serializer with data the state handler seeded, a producer regression will surface. If it returns a literal string or a copy of the pact's own contents, it verifies that two fixtures agree and will stay green through any real change.
saying these in an interview costs you the question
- Thinks the verifier consumes from a real topic
- Returns a hand-written JSON fixture from the producer method
- Confuses the state handler with the message-producing method
- Treats the interaction description as free-text documentation
- Believes a running broker is required to verify