I am using gomock, and I have this piece of example code that I wish to test.
type StructA struct {
client map[string]Foo
}
type Foo interface {
foo.methodFoo() string
}
func (a *structA) MethodA(name string) string {
client := a.client[name]
return client.methodFoo()
}
In my test, i've generated a mock for foo, called mockFoo. Used mockgen v1.6.0 to generate the mock for interface foo.
I have the test code as:
func Test_MethodA(t *testing.T) {
type fields struct {
client map[string]*mockFoo
}
tests := []struct {
fields fields
want string
}
{
// test cases
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := &StructA {
client: tt.fields.client //this has an error, saying that we cannot use map[string]*mockFoo as the type map[string]foo
}
...
})
}
}
TLDR is that map[string]*mockFoo
cannot be used as the type map[string]Foo
.
var foo1 Foo
var mockFoo1 *mockFoo
foo1 = mockFoo1 // no problem
var fooMap map[string]Foo
var mockFooMap map[string]*mockFoo
fooMap = mockFooMap // problematic
May I know if I'm doing anything wrong here or if this an expected behaviour? Thanks.
CodePudding user response:
Based on your description, Foo
is an interface, and *mockFoo
implements the Foo
interface. Thus, whenever a Foo
is required, you can used *mockFoo
.
The type map[string]Foo
is not the same as the type map[string]*mockFoo
. Both are concrete types (they are not interfaces), so you cannot substitute one for the other.
You can, however, use map[string]Foo
, and put *mockFoo
values into that map, and as far as I can see from your code, that's what you should do. Declare the map as map[string]Foo
, and use *mockFoo
values in it. If you need to refer to the values of the map as *mockFoo
, you can type-assert the map value to get the *mockFoo
value, that is:
fooMap=map[string]Foo{}
fooMap["key"]=mockFoo1
...
value:=foomap["key"].(*mockFoo)