Go中Mock实现无法匹配ClientProvider接口的问题求助
Go接口实现不匹配问题分析
问题描述
在Go应用中定义了MyClient接口、MyClients结构体(持有MyClient类型的映射,可根据key获取指定客户端),为测试创建了Mock版本,认为Mock应满足ClientProvider接口,但Go不认可该Mock实现——原因是Mock的Client方法返回MyClientMock(已实现MyClient接口)而非MyClient类型。
相关代码
client.go
type ClientProvider interface { Client(model string) MyClient } type MyClients struct { Clients map[string]MyClient } func (mc *MyClients) Client(client string) MyClient { return mc.Clients[client] } type MyClient interface { Get() }
client_mock.go
type MyClientsMock struct { Clients map[string]MyClientMock } func (mcm *MyClientsMock) Client(client string) MyClientMock { println("I an satisfying the ClientProvider Interface") return mcm.Clients[client] } type MyClientMock struct { MyClient Response string Err error } func (mcm MyClientMock) Get() { println("I an satisfying the MyClient Interface") } func NewMyClientsMock() MyClientsMock { return MyClientsMock{ Clients: map[string]MyClientMock{ "client-a": {Response: "hello from client a"}, "client-b": {Response: "hello from client b"}, }, } }
main.go
func main() { myClientsMock := NewMyClientsMock() // WHY CAN'T I DO THIS test(myClientsMock) } func test(clients ClientProvider) { }
错误原因
Go的接口实现要求方法签名完全一致,包括返回值类型:
ClientProvider接口规定Client方法必须返回MyClient接口类型MyClientsMock的Client方法返回的是具体类型MyClientMock,即使该类型实现了MyClient接口,返回类型不匹配就无法满足接口要求- 额外问题:
MyClientsMock的Client方法使用指针接收器,但NewMyClientsMock返回的是值类型,值类型无法实现带指针接收器的接口,这也是导致无法传入test函数的原因之一
解决方案
修改Mock实现以匹配接口要求
调整MyClientsMock的Client方法返回类型为MyClient,同时让NewMyClientsMock返回指针类型:
type MyClientsMock struct { Clients map[string]MyClientMock } // 修改返回类型为MyClient,MyClientMock实现了该接口,可直接返回 func (mcm *MyClientsMock) Client(client string) MyClient { println("I am satisfying the ClientProvider Interface") return mcm.Clients[client] } type MyClientMock struct { Response string Err error } // 移除冗余的MyClient嵌入,因为已经实现了Get方法 func (mcm MyClientMock) Get() { println("I am satisfying the MyClient Interface") } func NewMyClientsMock() *MyClientsMock { return &MyClientsMock{ Clients: map[string]MyClientMock{ "client-a": {Response: "hello from client a"}, "client-b": {Response: "hello from client b"}, }, } }
调整main.go调用
此时main.go中的调用即可正常运行:
func main() { myClientsMock := NewMyClientsMock() test(myClientsMock) } func test(clients ClientProvider) { }
内容的提问来源于stack exchange,提问作者mike73
相关产品推荐
相关产品推荐

