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.
- Protobuf-specific comparison: Uses
proto.Equalto 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.
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/protoequalMake 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/protobufThe 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.
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.
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))
}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.
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.
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.