Go如何获取Mock函数调用参数?类似Jest/Mockito的参数捕获
Go Mock工具如何捕获函数调用参数(类似Jest/mock.calls或Mockito/ArgumentCaptor)
是的,Go生态中基于gomock的Mock工具(包括Mockery和Mockgen)完全支持参数捕获功能,对应你提到的Jest或Mockito的用法,下面针对你的场景给出具体实现:
场景回顾
你有一个Client.SubmitForm方法,内部调用httpClient.Do(),希望在测试中捕获传入该Mock方法的*http.Request参数,验证其构造是否符合预期。
实现方案
1. 直接捕获参数到变量(类似ArgumentCaptor)
使用gomock.Capture函数可以将调用时的参数保存到变量中,之后对变量进行断言:
t.Run("should call Do with valid post request", func(t *testing.T) { ctx := context.Background() ctx = context.WithValue(ctx, utils.CTXAuthTokenKey, "value") // 声明变量用于捕获请求参数 var capturedReq *http.Request // 设置Mock期望时,用Capture捕获第三个参数 mockHTTPClient.EXPECT().Do( ctx, "SubmitCall", gomock.Capture(func(req *http.Request) { capturedReq = req }), ).Return(&http.Response{ StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewReader([]byte("SUCCESS"))), }, nil) // 执行被测方法 resp, err := client.SubmitForm(ctx) // 基础断言 assert.NoError(t, err) assert.Equal(t, "SUCCESS", resp) // 验证捕获到的请求参数 assert.Equal(t, http.MethodPost, capturedReq.Method) assert.Equal(t, "application/x-www-form-urlencoded", capturedReq.Header.Get("Content-Type")) // 验证URL parsedURL, _ := url.Parse(capturedReq.URL.String()) assert.Equal(t, "api.mytestservice.com", parsedURL.Host) assert.Equal(t, "/submit", parsedURL.Path) // 可继续验证请求体、Authorization头等其他字段 })
2. 匹配时直接验证参数(无需保存)
如果不需要保存参数,只想在Mock匹配阶段直接验证参数合法性,可以用gomock.MatchedBy:
t.Run("should send correct request details", func(t *testing.T) { ctx := context.Background() ctx = context.WithValue(ctx, utils.CTXAuthTokenKey, "value") mockHTTPClient.EXPECT().Do( ctx, "SubmitCall", gomock.MatchedBy(func(req *http.Request) bool { // 在这里直接校验请求的各项属性 return req.Method == http.MethodPost && req.Header.Get("Content-Type") == "application/x-www-form-urlencoded" && req.URL.Host == "api.mytestservice.com" && req.URL.Path == "/submit" }), ).Return(&http.Response{ StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewReader([]byte("SUCCESS"))), }, nil) resp, err := client.SubmitForm(ctx) assert.NoError(t, err) assert.Equal(t, "SUCCESS", resp) })
多调用场景的参数捕获
如果Mock方法会被多次调用,想要捕获所有调用的参数,可以用切片存储:
var capturedReqs []*http.Request mockHTTPClient.EXPECT().Do( gomock.Any(), gomock.Any(), gomock.Capture(func(req *http.Request) { capturedReqs = append(capturedReqs, req) }), ).Return(&http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewReader([]byte("SUCCESS")))}, nil).AnyTimes() // 执行被测逻辑后,遍历capturedReqs进行断言 for _, req := range capturedReqs { assert.Equal(t, http.MethodPost, req.Method) // 其他断言逻辑 }
内容的提问来源于stack exchange,提问作者Klaus
相关产品推荐
相关产品推荐

