使用Gomock进行测试会返回错误:预期的呼叫已被称为最大次数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Gomock进行测试会返回错误:预期的呼叫已被称为最大次数相关的知识,希望对你有一定的参考价值。

我正在使用Gomock https://godoc.org/github.com/golang/mock和mockgen

此测试的源代码是:

package sqs

import (
    "fmt"
    "log"
    "os"
    "runtime"

    "github.com/aws/aws-sdk-go/aws/session"

    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/service/sqs"
    "github.com/aws/aws-sdk-go/service/sqs/sqsiface"
)

var sess *session.Session
var svc *sqs.SQS
var queueURL string

func init() {
    // Setting the runtime to run with max CPUs available
    runtime.GOMAXPROCS(runtime.NumCPU())

    sess = session.Must(session.NewSessionWithOptions(session.Options{
        SharedConfigState: session.SharedConfigEnable,
    }))

    svc = sqs.New(sess)

    queueURL = os.Getenv("QUEUE_URL")
}

type Poller interface {
    Poll(chan bool)
}

// NewPoller is a factory to create a Poller object
func NewPoller(msgr Messenger) Poller {
    p := &poller{
        m: msgr,
    }
    return p
}

type poller struct {
    m Messenger
}

func (p *poller) Poll(done chan bool) {
    sqsMsgCh := make(chan *sqs.Message, 100)
    for {
        messages, err := p.m.GetMessage()
        if err != nil {
            log.Printf("error when getting message")
            if len(messages) == 0 {
                // Stop the system
                log.Printf("I am here")
                done <- true
            }
        }
        for _, msg := range messages {
            sqsMsgCh <- msg
        }
    }
}

type Messenger interface {
    GetMessage() ([]*sqs.Message, error)
}

func NewMessenger() Messenger {
    return &messenger{
        s: svc,
    }
}

type messenger struct {
    s sqsiface.SQSAPI
}

func (m *messenger) GetMessage() ([]*sqs.Message, error) {
    result, err := m.s.ReceiveMessage(&sqs.ReceiveMessageInput{
        AttributeNames: []*string{
            aws.String(sqs.MessageSystemAttributeNameSentTimestamp),
        },
        MessageAttributeNames: []*string{
            aws.String(sqs.QueueAttributeNameAll),
        },
        QueueUrl:            aws.String(queueURL),
        MaxNumberOfMessages: aws.Int64(10),
        VisibilityTimeout:   aws.Int64(36000), // 10 hours
        WaitTimeSeconds:     aws.Int64(0),
    })

    if err != nil {
        fmt.Println("Error", err)
        return nil, err
    }

    msgs := result.Messages
    if len(msgs) == 0 {
        fmt.Println("Received no messages")
        return msgs, err
    }
    return msgs, nil
}

此源文件的测试用例如下:

package sqs

import (
    "errors"
    "testing"

    "path_to_the_mocks_package/mocks"
    "github.com/golang/mock/gomock"

    "github.com/aws/aws-sdk-go/service/sqs"
)


func TestPollWhenNoMessageOnQueue(t *testing.T) {
    mockCtrl := gomock.NewController(t)
    defer mockCtrl.Finish()

    msgr := mocks.NewMockMessenger(mockCtrl)
    mq := make([]*sqs.Message, 1)
    err := errors.New("Mock Error")
    // msgr.EXPECT().GetMessage().Return(mq, err) //.Times(1)
    // msgr.GetMessage().Return(mq, err) //.Times(1)
    msgr.EXPECT().GetMessage().Return(mq, err)

    p := NewPoller(msgr)
    done := make(chan bool)
    go p.Poll(done)
    <-done
    t.Logf("Successfully done: %v", done)
}

当我运行测试时,我收到以下错误:

sqs controller.go:150:对path_to_mocks_package / mocks / mock_messenger.go:38的* mocks.MockMessenger.GetMessage([])的意外调用因为:在path_to_sqs_package / sqs / sqs_test.go:35处的预期调用已被称为最大次数。失败

如果我按如下方式编写自己的模拟,则测试用例成功执行:

type mockMessenger struct {
    mock.Mock
}

func (m *mockMessenger) GetMessage() ([]*sqs.Message, error) {
    msgs := make([]*sqs.Message, 0)
    err := errors.New("Error")
    return msgs, err
}
答案

你隐含地告诉gomock你只希望一个电话。

msgr.EXPECT().GetMessage().Return(mq, err)

在模拟中添加一些Times,允许您多次返回这些值。

msgr.EXPECT().GetMessage().Return(mq, err).AnyTimes()

以上是关于使用Gomock进行测试会返回错误:预期的呼叫已被称为最大次数的主要内容,如果未能解决你的问题,请参考以下文章

Go语言开发(二十一)GoMock测试框架

Go 接口嵌套组合的使用方法 & gomock 测试 stub 代码生成

“弄乱呼叫堆栈”是什么意思?

Laravel 测试 - 该名称已被使用

cms请求数据错误怎么处理

为啥使用 MKLocalSearch 会返回错误并且无法加载预期结果?