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