protoを比較しようとしてcmp.Diffでcmpops.IgnoreUnexportedを設定してもエラーになるとき
go でテストを書いていると、struct と struct の比較に google/go-cmpをよく使う
概ね問題なく使えるのだが struct の field に private な field があると外部 package から参照できず panic してしまう
consider using a custom Comparer; if you control the implementation of type, you can also consider using an Exporter, AllowUnexported, or cmpopts.IgnoreUnexported [recovered]
こんな感じのエラー表示される
エラーメッセージに表示されているとおり cmpopts.IgnoreUnexported
option を使えば、だいたいの場合で問題ない
if diff := cmp.Diff(got, want, cmpopts.IgnoreUnexported()); diff != "" {
t.Errorf("(-got +want)\n%v", diff)
}
で、今回は表題の通り cmpopts.IgnoreUnexported
を設定しても以前として panic してしまう
"google.golang.org/protobuf/types/known/timestamppb".Timestamp
consider using a custom Comparer; if you control the implementation of type, you can also consider using an Exporter, AllowUnexported, or cmpopts.IgnoreUnexported
色々調べてみると google.golang.org/protobuf/testing/protocmp
package の Transform
メソッドを使うとよいということが分かった
The google.protobuf.Any message is automatically unmarshaled such that the "value" field is a Message representing the underlying message value assuming it could be resolved and properly unmarshaled.
This does not directly transform higher-order composite Go types. For example, []*foopb.Message is not transformed into []Message, but rather the individual message elements of the slice are transformed.
ブログを読むとproto の API が変わったためらしい
最終的には以下のコードで上手くいった
if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
t.Errorf("(-got +want)\n%v", diff)
}
参考になれば
Discussion