1

假设我们有一个库提供了一个函数 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)
    }
}

这里的代码:https ://github.com/hotsnow/mock.git (stackoverflow 分支)

4

3 回答 3

1

你可以为此使用 gomock setarg函数

yourPackage.EXPECT().insert(&pointer).SetArg(0, newPointer)
于 2020-09-04T08:49:32.753 回答
1

您可以使用提供的Eq()matcher来实现这一点,它在内部调用reflect.DeepEqual()期望值和实际值;根据此方法的文档:

如果指针值使用 Go 的 == 运算符相等,或者它们指向深度相等的值,则它们是深度相等的。

假设我们有一个函数,它依赖于一个接受指针参数的接口方法:

package resource

type 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 test

import (
    "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{}值的指针,它仍会通过。

于 2021-10-12T11:55:04.430 回答
0

看来您不必使用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
}
于 2019-12-18T03:58:03.927 回答