Protobuf Payloads
Contract Testing compares Protobuf message payloads in consumer contracts with Protobuf schemas in AsyncAPI provider contracts. Each payload goes through a value check and a structure check. Between them, the checks catch changes that break the consumer, including changes that keep the payload valid but break Protobuf decoding.
For how comparison works for all payload formats, see Features - Testing AsyncAPI.
Requirements
Consumer Contract
Write the consumer contract with the Pact Protobuf plugin. The plugin embeds the consumer's Protobuf schema in the contract, and Contract Testing uses it for the structure check.
Use Pact Specification Version 4.
The interaction's content type must be application/protobuf or application/x-protobuf. The plugin sets it for you.
Reference the AsyncAPI operation in the same way as for JSON messages:
{
"type": "Asynchronous/Messages",
"comments": {
"references": {
"AsyncAPI": { "operationId": "receiveOrderPlaced" }
}
},
"contents": {
"contentType": "application/protobuf;message=.shop.OrderPlaced"
}
}Provider Contract
Define the message payload as a Multi Format Schema Object, with
schemaFormatset toapplication/vnd.google.protobuf. Aversionparameter is allowed, for exampleapplication/vnd.google.protobuf;version=3.Embed the
.protosource in the AsyncAPI definition. Contract Testing doesn't follow references to external files or schema registries.You can import Protobuf well-known types, such as
google/protobuf/timestamp.proto. Contract Testing can't resolve other imports, so a schema that uses them isn't compared.
components:
messages:
OrderPlaced:
contentType: application/protobuf
payload:
schemaFormat: application/vnd.google.protobuf;version=3
schema: |
syntax = "proto3";
package shop;
import "google/protobuf/timestamp.proto";
message OrderPlaced {
string order_id = 1;
int32 quantity = 2;
google.protobuf.Timestamp placed_at = 3;
}If Contract Testing can't select a message, the result is message.payload.unvalidatable.