猿问

我可以模拟一个带有需要使用的指针参数的函数吗

假设我们有一个库提供了一个 Double 函数来将整数加倍,我们使用指针 i 来获取结果值而不是通过返回:


package api


type Action interface {

    Double(i *int) error

}


type NUM struct{}


func (n NUM) Double(i *int) error {

    *i *= 2


    return nil

}

在我们的主函数中,我们使用这个库来完成我们的任务。像这样:


package app


import (

    "fmt"

    "github.com/hotsnow/api"

)


func main() {

    j := job{a: &api.NUM{}}

    d := j.task(3)

    fmt.Println(3, d)

}


type job struct {

    a api.Action

}


// double me

func (j job) task(i int) int {

    j.a.Double(&i)


    return i

}

现在我们需要测试task()函数,我们怎样才能通过模拟Double函数获得指针返回呢?


这是测试:


package app


import (

    "github.com/golang/mock/gomock"

    "github.com/hotsnow/mocks"

    "testing"

)


func TestReq(t *testing.T) {

    ctrl := gomock.NewController(t)

    defer ctrl.Finish()


    m := mocks.NewMockAction(ctrl)

    m.EXPECT().Double(gomock.Any()).Return(nil)


    j := job{a: m}

    got := j.task(3)

    if got != 6 {

        t.Errorf("got = %#v; want 6", got)

    }

}


白衣染霜花
浏览 139回答 3
3回答

江户川乱折腾

您可以为此使用 gomock setarg函数yourPackage.EXPECT().insert(&pointer).SetArg(0, newPointer)

翻过高山走不出你

您可以使用提供的Eq()matcher来实现此目的,它在内部调用reflect.DeepEqual()预期值和实际值;根据此方法的文档:如果使用 Go 的 == 运算符相等或者它们指向深度相等的值,则指针值深度相等。假设我们有一个函数依赖于带有指针参数的接口方法:package resourcetype ServiceRequest struct {    Name  string    Owner *string // this is a pointer so it can be omitted with `nil`}type Model struct {    // resource model...}type ResourceService interface {    Fetch(req *ServiceRequest) (Model, error)}type getResourceHandler struct {    resourceService ResourceService}type GetResourceEvent struct {    Resource string    Owner    *string}func NewResourceHandler(resourceService ResourceService) *getResourceHandler {    return &getResourceHandler{resourceService}}func (h *getResourceHandler) Handle(event GetResourceEvent) (Model, error) {    return h.resourceService.Fetch(&ServiceRequest{event.Resource, event.Owner})}我们可以Eq()在针对生成的接口模拟设置期望时使用匹配器ResourceService:package testimport (    "testing"    "github.com/golang/mock/gomock"    "github.com/stretchr/testify/assert"    "github.com/org/repo/internal/mock"    "github.com/org/repo/internal/resource")func optionalString(str string) *string {    return &str}func Test_GetResourceHandler_ReturnsResultFromService(t *testing.T) {    resourceName := "my-resource"    owner := optionalString("Joe Bloggs")    resourceReq := &resource.ServiceRequest{resourceName, owner}    event := resource.GetResourceEvent{resourceName, owner}    model := resource.Model{ /* fields here... */ }    ctrl := gomock.NewController(t)    mockResourceService := mock.NewMockResourceService(ctrl)    handler := resource.NewResourceHandler(mockResourceService)    mockResourceService.EXPECT().Fetch(gomock.Eq(resourceReq)).Return(model, nil)    res, err := handler.Handle(event)    assert.Nil(t, err)    assert.Equal(t, model, res)}如果您在测试或被测单元中更改服务请求的内容,您将看到测试不再通过。否则,尽管测试和被测单元有各自的指向单独ServiceRequest{}值的指针,它仍然会通过。

慕运维8079593

看来你不必使用gomock来测试该task方法。既然你有一个接口,为什么不直接创建该接口的模拟实现,例如:type dummy struct{    callCount int}func (d *dummy) Double(i *int) error {    d.callCount++    return nil}d := dummy{}j := job{a: &d}got := j.task(3)if d.callCount != 1 {    // XXX}
随时随地看视频慕课网APP

相关分类

Go
我要回答