小编典典

如何在Golang中测试地图的等效性?

go

我有一个像这样的表驱动测试用例:

func CountWords(s string) map[string]int

func TestCountWords(t *testing.T) {
  var tests = []struct {
    input string
    want map[string]int
  }{
    {"foo", map[string]int{"foo":1}},
    {"foo bar foo", map[string]int{"foo":2,"bar":1}},
  }
  for i, c := range tests {
    got := CountWords(c.input)
    // TODO test whether c.want == got
  }
}

我可以检查长度是否相同,并编写一个循环来检查每个键值对是否相同。但是,当我想将其用于另一种类型的地图(例如map[string]string)时,必须再次编写此检查。

我最终要做的是,将地图转换为字符串并比较了字符串:

func checkAsStrings(a,b interface{}) bool {
  return fmt.Sprintf("%v", a) != fmt.Sprintf("%v", b) 
}

//...
if checkAsStrings(got, c.want) {
  t.Errorf("Case #%v: Wanted: %v, got: %v", i, c.want, got)
}

假定等效映射的字符串表示形式相同,在这种情况下,这似乎是正确的(如果键相同,则它们会散列为相同的值,因此它们的顺序将相同)。有一个更好的方法吗?在表驱动测试中比较两个映射的惯用方式是什么?


阅读 310

收藏
2020-07-02

共1个答案

小编典典

Go库已经覆盖了您。做这个:

import "reflect"
// m1 and m2 are the maps we want to compare
eq := reflect.DeepEqual(m1, m2)
if eq {
    fmt.Println("They're equal.")
} else {
    fmt.Println("They're unequal.")
}

如果你看一下源代码reflect.DeepEqualMap情况下,你会发现,如果两个地图它首先检查是零,那么检查之前,他们具有相同的长度最后检查,看看他们是否有相同的一组(键,值)对。

由于reflect.DeepEqual采用接口类型,因此可以在任何有效的地图(map[string]bool, map[struct{}]interface{},等)上使用。请注意,它也适用于非地图值,因此请注意,传递给它的实际上是两个地图。如果您传递两个整数,它将很高兴地告诉您它们是否相等。

2020-07-02