亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何模擬在 Go 中將結果寫入其參數的函數

如何模擬在 Go 中將結果寫入其參數的函數

Go
慕碼人8056858 2022-05-23 17:49:03
我正在通過https://github.com/stretchr/testify在 golang 中編寫單元測試 假設我有以下方法,func DoSomething(result interface{}) error {    // write some data to result    return nil}所以調用者可以調用DoSomething如下result := &SomeStruct{}err := DoSomething(result)if err != nil {  fmt.Println(err)} else {  fmt.Println("The result is", result)}現在我知道如何使用testify或其他一些模擬工具來模擬返回值(它在err這里),比如mockObj.On("DoSomething", mock.Anything).Return(errors.New("mock error"))result我的問題是在這種情況下“我如何模擬論點”?由于result不是返回值而是參數,調用者通過傳遞一個結構的指針來調用它,函數對其進行修改。
查看完整描述

2 回答

?
慕尼黑8549860

TA貢獻1818條經驗 獲得超11個贊

您可以使用以下(*Call).Run方法:


Run 設置在返回之前調用的處理程序。它可以在模擬一個方法(例如解組器)時使用,該方法接受一個指向結構的指針并在該結構中設置屬性


例子:


mockObj.On("Unmarshal", mock.AnythingOfType("*map[string]interface{}")).Return().Run(func(args Arguments) {

    arg := args.Get(0).(*map[string]interface{})

    arg["foo"] = "bar"

})


查看完整回答
反對 回復 2022-05-23
?
鴻蒙傳說

TA貢獻1865條經驗 獲得超7個贊

services/message.go:


type messageService struct {

    HttpClient http.Client

    BaseURL    string

}

func (m *messageService) MarkAllMessages(accesstoken string) []*model.MarkedMessage {

    endpoint := m.BaseURL + "/message/mark_all"

    var res model.MarkAllMessagesResponse

    if err := m.HttpClient.Post(endpoint, &MarkAllMessagesRequestPayload{Accesstoken: accesstoken}, &res); err != nil {

        fmt.Println(err)

        return res.MarkedMsgs

    }

    return res.MarkedMsgs

}

我們傳遞res給m.HttpClient.Post方法。在此方法中,res將填充json.unmarshal方法。


mocks/http.go:


package mocks


import (

    "io"


    "github.com/stretchr/testify/mock"

)


type MockedHttp struct {

    mock.Mock

}


func (m *MockedHttp) Get(url string, data interface{}) error {

    args := m.Called(url, data)

    return args.Error(0)

}


func (m *MockedHttp) Post(url string, body interface{}, data interface{}) error {

    args := m.Called(url, body, data)

    return args.Error(0)

}

services/message_test.go:


package services_test


import (

    "errors"

    "reflect"

    "strconv"

    "testing"


    "github.com/stretchr/testify/mock"

    "github.com/mrdulin/gqlgen-cnode/graph/model"

    "github.com/mrdulin/gqlgen-cnode/services"

    "github.com/mrdulin/gqlgen-cnode/mocks"

)


const (

    baseURL     string = "http://localhost/api/v1"

    accesstoken string = "123"

)


func TestMessageService_MarkAllMessages(t *testing.T) {

    t.Run("should mark all messaages", func(t *testing.T) {

        testHttp := new(mocks.MockedHttp)

        var res model.MarkAllMessagesResponse

        var markedMsgs []*model.MarkedMessage

        for i := 1; i <= 3; i++ {

            markedMsgs = append(markedMsgs, &model.MarkedMessage{ID: strconv.Itoa(i)})

        }

        postBody := services.MarkAllMessagesRequestPayload{Accesstoken: accesstoken}

        testHttp.On("Post", baseURL+"/message/mark_all", &postBody, &res).Return(nil).Run(func(args mock.Arguments) {

            arg := args.Get(2).(*model.MarkAllMessagesResponse)

            arg.MarkedMsgs = markedMsgs

        })

        service := services.NewMessageService(testHttp, baseURL)

        got := service.MarkAllMessages(accesstoken)

        want := markedMsgs

        testHttp.AssertExpectations(t)

        if !reflect.DeepEqual(got, want) {

            t.Errorf("got wrong return value. got: %#v, want: %#v", got, want)

        }

    })


    t.Run("should print error and return empty slice", func(t *testing.T) {

        var res model.MarkAllMessagesResponse

        testHttp := new(mocks.MockedHttp)

        postBody := services.MarkAllMessagesRequestPayload{Accesstoken: accesstoken}

        testHttp.On("Post", baseURL+"/message/mark_all", &postBody, &res).Return(errors.New("network"))

        service := services.NewMessageService(testHttp, baseURL)

        got := service.MarkAllMessages(accesstoken)

        var want []*model.MarkedMessage

        testHttp.AssertExpectations(t)

        if !reflect.DeepEqual(got, want) {

            t.Errorf("got wrong return value. got: %#v, want: %#v", got, want)

        }

    })

}

在單元測試用例中,我們填充了res# Call.Run方法并將返回值(res.MarkedMsgs)分配service.MarkAllMessages(accesstoken)給got變量。


單元測試結果和覆蓋率:


=== RUN   TestMessageService_MarkAllMessages

--- PASS: TestMessageService_MarkAllMessages (0.00s)

=== RUN   TestMessageService_MarkAllMessages/should_mark_all_messaages

    TestMessageService_MarkAllMessages/should_mark_all_messaages: message_test.go:39: PASS: Post(string,*services.MarkAllMessagesRequestPayload,*model.MarkAllMessagesResponse)

    --- PASS: TestMessageService_MarkAllMessages/should_mark_all_messaages (0.00s)

=== RUN   TestMessageService_MarkAllMessages/should_print_error_and_return_empty_slice

network

    TestMessageService_MarkAllMessages/should_print_error_and_return_empty_slice: message_test.go:53: PASS: Post(string,*services.MarkAllMessagesRequestPayload,*model.MarkAllMessagesResponse)

    --- PASS: TestMessageService_MarkAllMessages/should_print_error_and_return_empty_slice (0.00s)

PASS

coverage: 5.6% of statements in ../../gqlgen-cnode/...


Process finished with exit code 0

http://img1.sycdn.imooc.com//628b58b800019b2011950182.jpg

查看完整回答
反對 回復 2022-05-23
  • 2 回答
  • 0 關注
  • 163 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號