Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question [Not a issue] #4

Closed
prvn opened this issue Dec 1, 2015 · 4 comments
Closed

Question [Not a issue] #4

prvn opened this issue Dec 1, 2015 · 4 comments

Comments

@prvn
Copy link

prvn commented Dec 1, 2015

Hello,
I am not sure how to ask a question, so opening a issue.

I am trying to mock a chain of function calls and i am not really getting how to do it from the documentation. Hope you can help me.

I am mocking redis client ("gopkg.in/redis.v3")

All calls to this API looks something like below

*redis.Client.ZAdd("test", data...).Result()
*redis.Client.ZRem("test", data...).Result()

Result() in ZAdd case belongs to struct *redis.IntCmd and Result() in ZRem case belongs to some other struct

How can I mock these API's ?

Appreciate your help

@maraino
Copy link
Owner

maraino commented Dec 3, 2015

Hi @prvn,

The redis package is not designed to be mockable, if you want to mock it you will need to create your own mockable wrapper.

Here you have an example:

package mock

import (
    "errors"
    "testing"

    "gopkg.in/redis.v3"
)

type Client struct {
    base redis.Client
}

func (c *Client) ZAdd(key string, members ...redis.Z) IntCmdInterface {
    return c.base.ZAdd(key, members...)
}

func (c *Client) ZRem(key string, members ...string) IntCmdInterface {
    return c.base.ZRem(key, members...)
}

type ClientInterface interface {
    ZAdd(key string, members ...redis.Z) IntCmdInterface
    ZRem(key string, members ...string) IntCmdInterface
}

type ClientMock struct {
    Mock
}

func (m *ClientMock) ZAdd(key string, members ...redis.Z) IntCmdInterface {
    ret := m.Called(key, members)
    return ret.Get(0).(IntCmdInterface)
}

func (m *ClientMock) ZRem(key string, members ...string) IntCmdInterface {
    ret := m.Called(key, members)
    return ret.Get(0).(IntCmdInterface)
}

type IntCmdInterface interface {
    Result() (int64, error)
}

type IntCmdMock struct {
    Mock
}

func (m *IntCmdMock) Result() (int64, error) {
    ret := m.Called()
    return ret.Int64(0), ret.Error(1)
}

func TestRedis(t *testing.T) {
    client := ClientMock{}
    cmd1 := &IntCmdMock{}
    cmd2 := &IntCmdMock{}
    cmd3 := &IntCmdMock{}

    cmd1.When("Result").Return(int64(123), nil)
    cmd2.When("Result").Return(int64(456), nil)
    cmd3.When("Result").Return(int64(0), errors.New("an error"))

    client.When("ZAdd", "foo", Any).Return(cmd1)
    client.When("ZRem", "bar", Any).Return(cmd2)
    client.When("ZRem", "zar", Any).Return(cmd3)

    ret := client.ZAdd("foo", redis.Z{1.00, "member"})
    if i, err := ret.Result(); i != 123 || err != nil {
        t.Fatal("Result is not 123")
    }

    ret = client.ZRem("bar")
    if i, err := ret.Result(); i != 456 || err != nil {
        t.Fatal("Result is not 456")
    }

    ret = client.ZRem("zar")
    if i, err := ret.Result(); i != 0 || err == nil || err.Error() != "an error" {
        t.Fatal("error is not `an error`")
    }
}

@maraino maraino closed this as completed Dec 3, 2015
@prvn
Copy link
Author

prvn commented Dec 3, 2015

That was super helpful! Thanks @maraino

@maraino
Copy link
Owner

maraino commented Dec 3, 2015

@prvn And of course as you're doing your own wrapper you can simplify the mock if you do things like:

func (c *Client) ZAdd(key string, members ...redis.Z) (int64, error) {
    return c.base.ZAdd(key, members...).Result()
}

@prvn
Copy link
Author

prvn commented Dec 3, 2015

I was thinking about the same, so that I can avoid mocking all the Result() functions of each Cmd structs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants