0

我是新来的。我正在尝试在我的 Go 例程中测试函数调用,但它失败并显示错误消息

预期调用次数 (8) 与实际调用次数 (0) 不匹配。

我的测试代码如下:

package executor

import (
    "testing"
  "sync"
    "github.com/stretchr/testify/mock"
)

type MockExecutor struct {
    mock.Mock
  wg sync.WaitGroup
}

func (m *MockExecutor) Execute() {
  defer m.wg.Done()
}

func TestScheduleWorksAsExpected(t *testing.T) {

    scheduler := GetScheduler()
    executor := &MockExecutor{}
    scheduler.AddExecutor(executor)

    // Mock exptectations
    executor.On("Execute").Return()
    

    // Function Call
  executor.wg.Add(8)
    scheduler.Schedule(2, 1, 4)
  executor.wg.Wait()

  executor.AssertNumberOfCalls(t, "Execute", 8)

}

我的应用程序代码是:

package executor

import (
    "sync"
    "time"
)

type Scheduler interface {
    Schedule(repeatRuns uint16, coolDown uint8, parallelRuns uint64)
    AddExecutor(executor Executor)
}

type RepeatScheduler struct {
    executor  Executor
    waitGroup sync.WaitGroup
}

func GetScheduler() Scheduler {
    return &RepeatScheduler{}
}

func (r *RepeatScheduler) singleRun() {
    defer r.waitGroup.Done()
    r.executor.Execute()
}

func (r *RepeatScheduler) AddExecutor(executor Executor) {
    r.executor = executor
}

func (r *RepeatScheduler) repeatRuns(parallelRuns uint64) {
    for count := 0; count < int(parallelRuns); count += 1 {
        r.waitGroup.Add(1)
        go r.singleRun()
    }

    r.waitGroup.Wait()
}

func (r *RepeatScheduler) Schedule(repeatRuns uint16, coolDown uint8, parallelRuns uint64) {

    for repeats := 0; repeats < int(repeatRuns); repeats += 1 {
        r.repeatRuns(parallelRuns)
        time.Sleep(time.Duration(coolDown))
    }

}

你能指出我在这里做错了什么吗?我正在使用 Go 1.16.3。当我调试我的代码时,我可以看到 Execute() 函数被调用,但 testify 无法注册函数调用

4

1 回答 1

2

您需要调用Called()以便记录已调用mock.Mock的事实。Execute()由于您不担心参数或返回值,因此以下内容应该可以解决您的问题:

func (m *MockExecutor) Execute() {
    defer m.wg.Done()
    m.Called()
}

但是我注意到你的测试当前编写的方式可能无法完成你想要的。这是因为:

  • 您在调用之前正在调用executor.wg.Wait()(它将等到该函数被调用了预期的次数),因此如果没有至少调用预期的次数(将永远阻塞)executor.AssertNumberOfCalls,您的测试将永远不会完成。Execute()wg.Wait()
  • m.Called()被调用了预期的次数之后,存在竞争条件(如果executor仍在运行,则在executor.AssertNumberOfCalls和 next之间存在竞争m.Called())。如果wg.Done()确实被调用了额外的时间,您会感到恐慌(我想您可能会认为失败!)但我可能会稍微简化测试:
scheduler.Schedule(2, 1, 4)
time.Sleep(time.Millisecond) // Wait long enough that all executions are guaranteed to have completed (should be quick as Schedule waits for go routines to end)
executor.AssertNumberOfCalls(t, "Execute", 8)
于 2021-05-06T02:06:30.603 回答