如何在Golang中实现Python的mock ANY

d7v8vwbk  于 2023-08-01  发布在  Go
关注(0)|答案(1)|浏览(126)

我希望能够比较两个字典,同时忽略某些字段的值。这在Python中使用mock.ANY非常容易。

  1. from unittest.mock import ANY
  2. actual = {'userName':'bob', 'lastModified':'2012-01-01'}
  3. expected = {'userName':'bob', 'lastModified': ANY}
  4. assert actual == expected

字符串
下面是我在Go语言中的尝试,它利用了cmp,允许你实现一个Equal方法(https://pkg.go.dev/github.com/google/go-cmp/cmp#Equal),但它不起作用。我相信这是因为我的MatchAll结构体不能“赋值”给string。有什么办法可以解决这个问题吗?

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/google/go-cmp/cmp"
  5. )
  6. type MatchAll string
  7. func (m MatchAll) Equal(v string) bool {
  8. return true
  9. }
  10. func main() {
  11. matchAll := MatchAll("bruh")
  12. actual := map[string]any{
  13. "key": matchAll,
  14. }
  15. expected := map[string]any{
  16. "key": "foobar",
  17. }
  18. fmt.Println(cmp.Equal(expected, actual))
  19. }

umuewwlo

umuewwlo1#

查看cmp代码,我认为这里的问题在于,当比较map元素时,用于检查Equal方法是否存在的类型是map的元素类型(这里是any),而不是两个值之一的具体类型(这里是stringMatchAll)。由于any类型没有声明Equal方法,因此它福尔斯到内置比较。
作为替代方案,您可以使用cmp.FilterValues和cmp.Comparer函数来构造一个支持特殊的“equal-to-anything”值的选项。例如,这看起来像预期的那样工作:

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/google/go-cmp/cmp"
  5. )
  6. type matchAllType struct{}
  7. var matchAll = matchAllType{}
  8. var matchAllOption = cmp.FilterValues(
  9. // Filter function: returns `true` only for values using this comparison.
  10. func(x, y any) bool {
  11. return x == matchAll || y == matchAll
  12. },
  13. // Comparison function: called for pairs of values the filter accepts.
  14. cmp.Comparer(func(x, y any) bool { return true }),
  15. )
  16. func main() {
  17. actual := map[string]any{
  18. "key": matchAll,
  19. }
  20. expected := map[string]any{
  21. "key": "foobar",
  22. }
  23. fmt.Println(cmp.Equal(expected, actual, matchAllOption))
  24. }

字符串
always-true比较函数也可以用cmp.Ignore()代替,尽管我不完全确定语义是否完全相同。至少在上面的例子中是这样的。
还有一个cmpopts.IgnoreMapEntries选项,可以按如下方式使用,但语义略有不同:

  1. var matchAllOption = cmpopts.IgnoreMapEntries(func(_, v any) bool { return v == matchAll })


不同之处在于,使用此选项,即使actual字典根本不包含具有匹配键的条目,比较结果也将是true,因为内置的Map比较测试是否“递归地调用Equal on * 所有未忽略的Map条目 * report equal”,重点添加。相比之下,早期的解决方案仍然需要另一个Map包含具有相同键的 some 值。

展开查看全部

相关问题