Go语言 如何记录模拟函数调用的参数值

5rgfhyps  于 2023-01-18  发布在  Go
关注(0)|答案(1)|浏览(138)

我正在尝试将被调用的参数值传递给一个mock函数,Go语言mock的功能是否类似于Jest中的someMockFunction.mock.calls[0][0]).toBe('first arg')或者Mockito中的ArgumentCaptor
这是我的用例。
我有一个调用外部API的Client结构体。

func (c *Client) SubmitForm(ctx context.Context ) (string, error) {
     formVals := url.Values{}
     // Payload created here

     apiUrl := url.URL{Scheme: "http", Host: "api.mytestservice.com, Path: "/submit"}

     httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, apiUrl.String(), strings.NewReader(formVals.Encode()))
     httpReq.Header.Set("Authorization", <sometoken>)
     httpReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")

     resp, err := c.httpClient.Do(ctx, submitPickupSchedule, httpReq) // This calls to a mock httpClient.Do()

     // error handling and return values goes here
     return resp, err
}

我的模拟是用Mockery创建的(我也试过Mockgen)。

mockHTTPClient := mock_httputils.NewMockHTTPClient(ctrl)
client = Client{httpClient: mockHTTPClient} // Using the mock HTTP client here

t.Run("should call the Do with post request successfully", func(t *testing.T) {
    ctx := context.Background()
    ctx = context.WithValue(ctx, utils.CTXAuthTokenKey, "value")

    mockHTTPClient.EXPECT().Do(ctx, "SubmitCall",
        gomock.Any()).Return(&http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewReader([]byte("SUCCESS")))}, nil)

    resp, err := client.SubmitForm(ctx)
    // assertions here and everything works as expected. It calls the mock method.
}

在调用模拟Do()之后,我试图获取调用到该函数中的实际参数。也就是说,我想检查在SubmitForm方法中创建并传递到此模拟Do()中的req对象。
在GoLang有办法做到这一点吗?

laik7k3q

laik7k3q1#

在@mkopriva的评论之后,我能够在一个模拟函数中捕获参数。在这里发布我的解决方案,以便将来对任何人都有帮助。

func TestArgumentCaptor(t *testing.T){
        var req *http.Request // To record the request attributes

        // Original HTTPClient Do(ctx context.Context, name string, req *http.Request) (resp *http.Response, err error) has this signature
        mockHTTPClient.EXPECT().Do(ctx, "Submit", gomock.Any()).DoAndReturn(
            // signature of the anonymous function must have the same method signature as the original method
            func(argCtx context.Context, argName string, argReq *http.Request) (resp *http.Response, err error) {
                req = argReq
                return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewReader([]byte("SUCCESS")))}, nil
            })

        mockHTTPClient.DoCall() // Calls the mockHTTPClient.Do() method.

        // URI check
        assert.NotNil(t, req)
        assert.Equal(t, req.URL.Scheme, <expected-scheme>, "URL scheme mismatch")
        assert.Equal(t, req.URL.Host, <expected-hist>, "Host mismatch")
        assert.Equal(t, req.URL.Path, <expected-path>, "Path mismatch")

        // Headers check
        assert.Equal(t, req.Header.Get("Authorization"),<expected-header>)
        assert.Equal(t, req.Header.Get("Content-Type"), <expected-header>)

 }

相关问题