使用依赖注入测试包装函数

我有这个函数,我需要在测试中模拟,我能够用 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

}

知道如何为此功能运行测试吗???我为此苦苦挣扎。


智慧大石
浏览 88回答 2
2回答

Cats萌萌

独立于原始问题,您不应该为每个请求创建新的 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.}

宝慕林4294392

由于 Service 结构已经有一个 req 接口,在测试期间使用满足 req 接口的 mock 初始化服务对象。
打开App,查看更多内容
随时随地看视频慕课网APP