使用Gomock时map[string]*mockFoo无法赋值给map[string]Foo问题
结论
这是Go语言的预期行为,和gomock的使用方式无关。
原因说明
- 单个变量赋值合法的原因:
*mockFoo类型实现了Foo接口,符合Go接口的赋值规则,因此*mockFoo实例可以直接赋值给Foo类型的变量,没有类型错误。 - Map赋值不合法的原因:
map[string]Foo和map[string]*mockFoo是两个完全独立的不同类型,Go的类型系统不支持泛型容器的协变/逆变,不会因为容器的元素类型存在接口实现关系,就认为整个容器类型兼容。类似的规则也适用于切片、通道等容器类型,比如[]*mockFoo也不能直接赋值给[]Foo。
修复方案
推荐直接调整测试代码中字段的声明类型,直接使用接口类型的map即可:
func Test_MethodA(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() type fields struct { client map[string]Foo // 替换原来的map[string]*mockFoo } tests := []struct { name string fields fields want string }{ { name: "正常测试用例", fields: fields{ client: func() map[string]Foo { mockFooInst := NewMockFoo(ctrl) mockFooInst.EXPECT().methodFoo().Return("预期返回值") return map[string]Foo{ "test_name": mockFooInst, } }(), }, want: "预期返回值", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { a := &StructA { client: tt.fields.client, } res := a.MethodA("test_name") if res != tt.want { t.Errorf("MethodA() = %v, want %v", res, tt.want) } }) } }
如果确实有需要保留map[string]*mockFoo类型的场景,可以手动遍历做类型转换:
fooMap := make(map[string]Foo, len(tt.fields.client)) for k, v := range tt.fields.client { fooMap[k] = v } a := &StructA{client: fooMap}
内容的提问来源于stack exchange,提问作者kito
相关产品推荐
相关产品推荐

