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

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

使用依賴注入測試包裝函數

使用依賴注入測試包裝函數

Go
智慧大石 2023-05-22 15:50:09
我有這個函數,我需要在測試中模擬,我能夠用 http mock package 模擬它,但現在我有調用方法的函數,在這里我不能使用 http HttpReqmock package 我讀過關于依賴注入并嘗試了一些但我無法完全做到,這是功能type params struct {    cs     string    ci     string    method string    url    string}// I added this struct but not sure if it's needed ... probably for test purpose but not sure how to use it.type Impl struct { client *http.Client}func (i *Impl) HttpReq(p *params) ([]byte, error) {    httpClient := i.client    req, err := http.NewRequest(p.method, p.url, nil)    if err != nil {        fmt.Sprintf(err)    }    req.SetBasicAuth(p.cs, p.ci)    res, err := httpClient.Do(req)    if err != nil {        fmt.Sprintf(err)    }    t, err := ioutil.ReadAll(res.Body)    if err != nil {        fmt.Sprintf(err)    }    defer res.Body.Close()    return t, nil}這是我試過的我創建了界面type Req interface {    HttpReq(params) ([]byte, error)}現在我創建了一個包含接口的結構type Service struct {    req Req}這是我需要測試的功能func (c *Service) execute(cli Connection , args []string) (error, []byte) {    sk, err := c.doSomthing(cli, args)    sc, err := c.doSometing2(serviceK, []string{"url", "cl", "ct"})    cc := strings.Fields(serviceCredentials)    // ----------Here is what I need to mock ----------    t, err := c.req.HttpReq(params{cs: cc[1],        ci:     cc[2],        method: http.MethodPost,        url:    cc[0],})    return err, t}知道如何為此功能運行測試嗎???我為此苦苦掙扎。
查看完整描述

2 回答

?
Cats萌萌

TA貢獻1805條經驗 獲得超9個贊

獨立于原始問題,您不應該為每個請求創建新的 HTTP 客戶端。客戶端維護一個連接池,應盡可能重用。

您可以解決這個問題,并通過注入 HTTP 客戶端繼續使用現有的模擬服務器。

另請注意,問題中的接口定義與實現不匹配。這兩個方法簽名是不一樣的:

HttpReq(params)?([]byte,?error)??//?Req
HttpReq(*params)?([]byte,?error)?//?Impl

選一個。我可能會在這里使用非指針類型。大寫首字母在 Go 中是慣用的(HTTPReq, not?HttpReq)。

將客戶端添加到Impl類型中并將其用于HTTPReq

type Impl struct {

? ? client *http.Client

}


func (i *Impl) HTTPReq(p params) ([]byte, error) {

? ? req, err := http.NewRequest(p.method, p.url, nil)

? ? if err != nil {

? ? ? ? return nil, err

? ? }

? ? req.SetBasicAuth(p.cs, p.ci)


? ? res, err := i.client.Do(req)

? ? if err != nil {

? ? ? ? return nil, err

? ? }

? ? defer res.Body.Close()


? ? return ioutil.ReadAll(res.Body)

}

服務類型不必更改。


在測試中,只需將測試客戶端注入到Impl值中:


import (

? ? "context"

? ? "net"

? ? "net/http"

? ? "net/http/httptest"

? ? "testing"

)


func TestService_execute(t *testing.T) {

? ? var testHandler http.Handler // TODO


? ? srv := httptest.NewServer(testHandler)

? ? defer srv.Close()


? ? client := srv.Client()

? ? tp := client.Transport.(*http.Transport)


? ? // Direct all requests to the test server, no matter what the request URL is.

? ? tp.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {

? ? ? ? // Note that we ignore the network and addr parameters, since these are?

? ? ? ? // derived from the request URL and are unrelated to the test server.


? ? ? ? srvAddr := srv.Listener.Addr()

? ? ? ? return (&net.Dialer{}).DialContext(ctx, srvAddr.Network(), srvAddr.String())

? ? }


? ? svc := &Service{

? ? ? ? req: &Impl{

? ? ? ? ? ? client: client,

? ? ? ? },

? ? }


? ? svc.execute(/* ... */)


? ? // assert request, response, etc.

}


查看完整回答
反對 回復 2023-05-22
?
寶慕林4294392

TA貢獻2021條經驗 獲得超8個贊

由于 Service 結構已經有一個 req 接口,在測試期間使用滿足 req 接口的 mock 初始化服務對象。

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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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