Skip to content

Custom Gomega matcher for comparing Protocol Buffer messages

License

Notifications You must be signed in to change notification settings

afritzler/protoequal

Repository files navigation

ProtoEqual Matcher for Gomega

ProtoEqual is a custom matcher designed for comparing Protocol Buffer messages in Go. It allows you to focus on the meaningful fields of protobuf messages and ignores internal fields such as state, sizeCache, and unknownFields, which are generated by the google.golang.org/protobuf package.

Features

  • Protobuf-specific comparison: Uses proto.Equal to compare the actual content of protobuf messages, ignoring any internal state or metadata fields.
  • Seamless integration with Gomega: Works like other Gomega matchers for easy use in unit tests.
  • Support for nested protobuf messages: Handles complex protobuf structures with nested messages.

Installation

To add the ProtoEqual dependency to your project, you can reference this repository. Use the following command to add it:

go get github.com/afritzler/protoequal

Make sure you also have the Protocol Buffers Go plugin installed if you're working with .proto files. You can install it using:

go get google.golang.org/protobuf

Usage

Using ProtoEqual in Unit Tests

The ProtoEqual matcher is used to compare Protocol Buffer messages within Gomega-based tests. It helps you compare protobuf messages without worrying about internal fields added by the protobuf compiler.

Example Protobuf Messages

Assume you have the following .proto file defining Foo and Qux messages:

syntax = "proto3";

package api.v1;
option go_package = "github.com/afritzler/protoequal/test/api/v1";

// The Foo message with Bar, Baz fields and a nested message Qux.
message Foo {
  string bar = 1; // Bar field
  string baz = 2; // Baz field
  Qux qux = 3;    // Qux is a nested message
}

// The Qux message with Driver and Handle fields.
message Qux {
  string driver = 1; // Driver field
  string handle = 2; // Handle field
}

After generating the Go code using protoc, you can now write tests comparing Foo messages using ProtoEqual.

Example Test with Gomega

Here is an example of how to use the ProtoEqual matcher in a test:

package matchers_test

import (
    "testing"
    
    "google.golang.org/protobuf/proto"
    . "github.com/afritzler/protoequal" 
    "github.com/afritzler/protoequal/test/api/v1"
    "github.com/onsi/gomega"
)

func TestProtoEqualMatcher(t *testing.T) {
    g := gomega.NewWithT(t)

    // Define two identical Foo messages
    actualMessage := &test.Foo{
        Bar: "foo-bar",
        Baz: "foo-baz",
        Qux: &test.Qux{
            Driver: "foo-driver",
            Handle: "foo-handle",
        },
    }

    expectedMessage := &test.Foo{
        Bar: "foo-bar",
        Baz: "foo-baz",
        Qux: &test.Qux{
            Driver: "foo-driver",
            Handle: "foo-handle",
        },
    }

    // Use ProtoEqual to assert that actualMessage matches expectedMessage
    g.Expect(actualMessage).To(ProtoEqual(expectedMessage))
}

Using Nested Protobuf Messages

Since ProtoEqual uses proto.Equal internally, it automatically handles nested messages. For example, in the Foo message, the nested Qux message is compared as part of the overall structure.

Why Use ProtoEqual?

When comparing protobuf messages directly in Go, the default equality check will include internal fields generated by the Protobuf compiler (e.g., state, sizeCache). These fields are not relevant to the content of the message and can cause tests to fail even when the message data is identical. ProtoEqual solves this by ignoring these internal fields and focusing only on the actual message content.

License

This project is licensed under the Apache 2.0 License. See the LICENSE file for details.