Golang模拟函数被调用两次

5

我正在编写针对main.go的单元测试,在函数内部调用了Get函数(DeviceRepo.Get())两次,我希望模拟Get函数返回不同结果,但是只能在第一次调用时进行模拟。那么我该如何在第二次调用时模拟Get函数呢?

main.go:

type DeviceInterface interface {}
type DeviceStruct struct{}

var DeviceRepo repositories.DeviceRepoInterface =  &repositories.DeviceRepoStruct{}

func (d *DeviceStruct) CheckDevice(familyname string, name string, firmwareversion string) string {
deviceList, deviceListErr := DeviceRepo.Get(familyname, name, firmwareversion)

if deviceListErr != "" {
    return "some error"
}

if len(deviceList) == 0 {
    deviceList, _ := DeviceRepo.Get(familyname, name, "")

    if len(deviceList) > 0 {
        return "Invalid firmware version."
    } else {
        return "Unknown device."
    }
}

return "Success"
}

main_test.go:

  type MockGetDeviceList struct {
    returnResult []resources.DeviceListDataReturn
    returnError  string
  }

  func (m *MockGetDeviceList) Get(familyName string, name string, firmwareVersion string) ([]resources.DeviceListDataReturn, string) {
    return m.returnResult, m.returnError
  }

  func Test_CheckDevice_WrongFirmwareVersion(t *testing.T) {
   Convey("Test_CheckDevice_WrongFirmwareVersion", t, func() {
    familyNameMock := "A"
    nameMock := "A"
    firmwareVersionMock := "3"

    mockReturnData := []resources.DeviceListDataReturn{}

    mockReturnDataSecond := []resources.DeviceListDataReturn{
        {
            FamilyName:      "f",
            Name:            "n",
            FirmwareVersion: "1.0",
        },
    }

    deviceModel := DeviceStruct{}

    getDeviceList := DeviceRepo
    defer func() { DeviceRepo = getDeviceList }()
    DeviceRepo = &MockGetDeviceList{returnResult: mockReturnData}

    getDeviceList = DeviceRepo
    defer func() { DeviceRepo = getDeviceList }()
    DeviceRepo = &MockGetDeviceList{returnResult: mockReturnDataSecond}

    expectReturn := "Invalid firmware version."

    actualResponse := deviceModel.CheckDevice(familyNameMock, nameMock, firmwareVersionMock)

    Convey("Checking check-device wrong firmware version", func() {
        So(actualResponse, ShouldEqual, expectReturn)
    })
})
}

我希望在第一次调用Get函数时模拟返回 []resources.DeviceListDataReturn{},然后在第二次调用时返回 []resources.DeviceListDataReturn{ { FamilyName: "f", Name: "n", FirmwareVersion: "1.0", }, }。

2个回答

6
你可以使用 https://pkg.go.dev/github.com/stretchr/testify/mock#Call.Once
mock.On("Get", mock.Anything).Return(mockReturnData).Once()
mock.On("Get", mock.Anything).Return(mockReturnData2).Once()

如果您知道可以传递哪些参数,那么可以这样做:

mock.On("Get", "lastName", "name", "version").Return(mockReturnData)
mock.On("Get", "lastName_2", "name_2", "version_2").Return(mockReturnData2)

0
任何函数或方法要根据调用次数而有所不同,就需要在其中提供这些信息。
最简单的方法是在每次调用时添加和递增一个计数器,在函数内部检查计数器的当前值,并根据其值采取不同的行动:
type MockGetDeviceList struct {
    returnResult []resources.DeviceListDataReturn
    returnError  string
    getCount     int
}

func (m *MockGetDeviceList) Get(familyName string, name string,
    firmwareVersion string) ([]resources.DeviceListDataReturn, string) {

    m.getCount++
    if m.getCount == 1 {
        // First call:
        return nil, m.returnError
    }
    // Sencond and subsequent calls:
    return m.returnResult, ""
}

另一种解决方案是在第一次调用后替换模拟对象/函数,但这种解决方案更难理解,更脆弱且不易维护。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接