我有一个问题,我需要将两个非常大的结构(生成的 protobuf)相互比较,作为测试用例的一部分。这些结构体中有多个嵌套数组。下面是一个重现/演示该问题的简化示例。
package pkg
import (
"github.com/stretchr/testify/assert"
"reflect"
"testing"
)
type structOne struct {
Foo string
Offs []*structTwo
}
type structTwo struct {
Identifier string
}
func Test_Compare(t *testing.T) {
exp := &structOne{
Foo: "bar",
Offs: []*structTwo{
{
Identifier: "one",
},
{
Identifier: "two",
},
{
Identifier: "three",
},
{
Identifier: "four",
},
},
}
act := &structOne{
Foo: "bar",
Offs: []*structTwo{
{
Identifier: "four",
},
{
Identifier: "three",
},
{
Identifier: "two",
},
{
Identifier: "one",
},
},
}
assert.Equal(t, exp, act) // fails
assert.True(t, reflect.DeepEqual(exp, act)) // fails
}
Run Code Online (Sandbox Code Playgroud)
我尝试过使用assert.Equal(t, exp, act)
和assert.True(t, reflect.DeepEqual(exp, act))
。我正在寻找一种比较此类结构的方法,最好不必为所有对象创建自定义比较函数。
谢谢
您可以用来assert.ElementsMatch
比较两个切片,而不管元素顺序如何。
ElementsMatch 断言指定的 listA(array, slice...) 等于指定的 listB(array, slice...) ,忽略元素的顺序。如果存在重复元素,则两个列表中每个元素的出现次数应该匹配。
然而,这仅适用于切片字段本身。如果你的结构体模型的字段很少,你可以一一比较它们并ElementsMatch
在切片上使用:
assert.Equal(t, exp.Foo, act.Foo)
assert.ElementsMatch(t, exp.Offs, act.Offs)
Run Code Online (Sandbox Code Playgroud)
如果您的结构有很多字段,您可以将切片值重新分配给临时变量,将nil
字段取出,然后进行比较:
expOffs := exp.Offs
actOffs := act.Offs
exp.Offs = nil
act.Offs = nil
assert.Equal(t, exp, act) // comparing full structs without Offs
assert.ElementsMatch(t, expOffs, actOffs) // comparing Offs separately
Run Code Online (Sandbox Code Playgroud)
stretchr/testify
如果允许为用户定义类型注册自定义比较器,或者检查对象是否实现某个接口并调用它来测试相等性,那就更好了
if cmp, ok := listA.(Comparator); ok {
cmp.Compare(listB)
}
Run Code Online (Sandbox Code Playgroud)
但我不知道有这样的功能。
或者,https://github.com/r3labs/diff
建议您可以这样使用。默认情况下会忽略顺序或切片项。
// import "github.com/r3labs/diff/v2"
changelog, err := diff.Diff(exp, act)
assert.NoError(t, err)
assert.Len(t, changelog, 0)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7201 次 |
最近记录: |