EN VI

Go - Using a mock implementation as an argument for a function expecting an interface?

2024-03-11 18:00:08
How to Go - Using a mock implementation as an argument for a function expecting an interface

In my go application, I have a MyClient struct and a MyClients struct which holds a map of MyClient. The idea is that depending on your needs you can request a specific client by a key.

For testing, I created a mock version which as far as I can tell should satisfy all of the interfaces I declared. However, Go doesn't like that my mock implementation of the Client method returns a MockClient (which satisfies the MyClient interface) instead of a MyClient.

Can someone please point out what I am doing wrong, or why this doesn't work. I'm missing something obvious I feel.

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) {

}

Solution:

Go doesn't like that my mock implementation of the Client method returns a MockClient (which satisfies the MyClient interface) instead of a MyClient.

It's totally fine for the method to return a MyClientMock (since any MyClientMock is a MyClient), but its declared return-type needs to be MyClient in order to satisfy the interface:

func (mcm *MyClientsMock) Client(client string) MyClient {
    println("I an satisfying the ClientProvider Interface")
    return mcm.Clients[client]
}
Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login