3

I would like to Mock the response of a function. But this function is located or called inside another function. Let say I have this function

// main.go
func TheFunction() int {
   // Some code
   val := ToMockResponse()
   return val
}

func ToMockResponse() int {
    return 123
}

Now on my test file

// main_test.go
func TestTheFunction(t *testing.T) {
    mockInstance = new(randomMock)
    mockInstance.On("ToMockResponse").Return(456)

    returned := TheFunction()
    assert.Equal(t, 456, returned)
}

As you can see within function TheFunction() a call to function ToMockResponse is made. Now I would like to test TheFunction but I would like to Mock the response of ToMockResponse how can I achieve this?

MadzQuestioning
  • 3,341
  • 8
  • 45
  • 76
  • Make ToMockResponse a global variable ans change its value to your mock implementation. One more advice: Stop mocking and asserting in Go tests. Take a look at the tests in the standard library and learn from there. – Volker Jun 07 '18 at 03:36
  • 1
    @volker Perhaps some people don't call them mocks but even in the standard library tests they create objects that match an interface and use them to stub out external factors in tests. – Levsero Jun 07 '18 at 21:56

2 Answers2

1

You should consider passing in the second function is as an parameter to the first.

You have a few options for doing that. You could simply pass it as a parameter.

func DoX(doY func()) {
   doY()
}

That’s simple but doesn’t work well as the core get more complex. The better alternative is often to make the functions methods on a struct.

type X struct {
   Y Y
}

type Y interface {
   Do()
}

func (x *X) Do() {
   x.Y.Do()
}

Then Y can be replaced with a mock.

dolan
  • 1,716
  • 11
  • 22
0

Let's consider we have two functions, executor() and process() where executor function calls process function,

We need to write both the functions as shown below with structures and interfaces:

main.go is as shown below:

package main

import "fmt"

// A structure defined which will have a value of type processHandler(interface)
// This is helpful  to pass a structure instance of processData later(see in main function)
// This is required to pass mock instance also
type processDataHandler struct{ procData processHandler }

// Interface defined for process method
type processHandler interface {
    process() (int, string)
}

// structure on top of which executor method is getting called
type processData struct{}

// process method called by executor method
func (p processData) process() (int, string) {
    return 23, "test2"
}

// executor method which has "processDataHandler" as argument
func (e processDataHandler) executor() (int, string) {
    // Some code
    //process function call
    val, str_val := e.procData.process()
    if val == 23 {
        return 40, "success"
    }
    return 45, str_val
}

func main() {
    procData := processData{}
    dataHandle := processDataHandler{procData: procData}
    val1, val2 := dataHandle.executor()

    fmt.Println(val1)

    fmt.Println(val2)

}

main_test.go is as shown below:

package main

import (
    "testing"

    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/mock"
)

//Define a mock insatnce
type processDataMock struct {
    mock.Mock
}

func (m *processDataMock) process() (int, string) {
    // this records that the method was called and passes in the value
    // it was called with
    args := m.Called()
    // it then returns whatever we tell it to return
    // in this case we are returing a integer type followed by a string type
    return args.Int(0), args.String(1)
}

//Test function for executor method
func TestExecutor(t *testing.T) {
    //define mock instance
    procMock := new(processDataMock)
    //Make process function to return 1 and "test" via mock
    procMock.On("process").Return(1, "test")
    //create a processDatahandler with mock instance
    handler := processDataHandler{procData: procMock}
    //call executor function which inturn mocks process via "procMock.On" above
    a, b := handler.executor()

    assert.Equal(t, 45, a)
    assert.Equal(t, "test", b)

}
Chandan
  • 704
  • 7
  • 20