假设我们有一个库提供了一个函数 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
}
在我们的 main 函数中,我们使用此库来完成我们的任务。 像这样:
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(( 函数,我们如何让指针返回 bye mock 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(堆栈溢出分支(
你可以为此使用 gomock setarg 函数
yourPackage.EXPECT().insert(&pointer).SetArg(0, newPointer)
您可以使用提供的Eq()
匹配器来实现此目的,该匹配器在内部调用reflect.DeepEqual()
期望值和实际值;根据此方法的文档:
相等的值,则指针值是深度相等的。
假设我们有一个函数,它依赖于一个接受指针参数的接口方法:
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})
}
我们可以在针对生成的ResourceService
接口模拟设置期望时使用Eq()
匹配器:
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{}
值,但它仍将通过。
似乎您不必使用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
}