簡體   English   中英

使用stretchr/testify比較具有忽略項目順序的切片字段的結構

[英]Compare structs that have slice fields ignoring item order with stretchr/testify

我有一個問題,我需要將兩個非常大的結構(生成的 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
}

我試過使用assert.Equal(t, exp, act)assert.True(t, reflect.DeepEqual(exp, act)) 我正在尋找一種比較此類結構的方法,最好無需為所有對象創建自定義比較函數。

謝謝

嘗試檢查這個https://github.com/r3labs/diff

它也應該有助於將結構與自定義類型進行比較!

無論元素順序如何,您都可以使用assert.ElementsMatch來比較兩個切片。

ElementsMatch 斷言指定的 listA(array, slice...) 等於指定的 listB(array, slice...) 忽略元素的順序。 如果有重復的元素,它們在兩個列表中的出現次數應該匹配。

然而,這僅適用於切片字段本身。 如果你的 struct 模型的字段很少,你可以一一比較它們並在切片上使用ElementsMatch

    assert.Equal(t, exp.Foo, act.Foo)
    assert.ElementsMatch(t, exp.Offs, act.Offs)

如果您的結構有很多領域,你可以重新切片值的臨時變量, 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

如果stretchr/testify允許為用戶定義的類型注冊自定義比較器,或者檢查對象是否實現某個接口並調用它來測試相等性,那就更好了

if cmp, ok := listA.(Comparator); ok { 
    cmp.Compare(listB) 
}

但我不知道這樣的功能。

為我自己的問題提供答案,因為這是一種適用於我的案例的方法。

使用這個庫解決了這個問題: https : //github.com/r3labs/diff

然后我可以斷言更改列表為空。 今天早些時候的一個用戶提供了這個作為有效的答案,但在我回復之前用戶刪除了答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM