Testify Макет возврата функции внутри функции

Я хотел бы высмеивать ответ функции. Но эта функция находится или вызывается внутри другой функции. Скажем у меня есть эта функция

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

func ToMockResponse() int {
    return 123
}

Теперь на моем тестовом файле

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

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

Как вы можете видеть внутри функции TheFunction(), вызывается функция ToMockResponse. Теперь я хотел бы протестировать TheFunction, но я хотел бы высказать ответ ToMockResponse, как мне этого добиться?

2 ответа

Решение

Вы должны рассмотреть возможность передачи второй функции в качестве параметра первой.

У вас есть несколько вариантов для этого. Вы можете просто передать его в качестве параметра.

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

Это просто, но не работает, так как ядро ​​становится более сложным. Лучшей альтернативой часто является создание методов функций в структуре.

type X struct {
   Y Y
}

type Y interface {
   Do()
}

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

Тогда Y можно заменить на макет.

Предположим, у нас есть две функции,executor()иprocess()где функция-исполнитель вызывает функцию процесса,

Нам нужно написать обе функции, как показано ниже, со структурами и интерфейсами:

main.goкак показано ниже:

      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как показано ниже:

      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)

}
Другие вопросы по тегам