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 schemaFormat set to application/vnd.google.protobuf. A version parameter is allowed, for example application/vnd.google.protobuf;version=3.

  • Embed the .proto source 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.

Publication date: