测试包裹功能和依赖注入



我有这个功能,我需要在测试中模拟,我能够按照HTTP模拟软件包按预期进行模拟,但是现在我正在调用的功能到HttpReq方法,在这里我无法使用HTTP模拟软件包我读了有关依赖注射的信息,但尝试了一些东西,但我无法完全做到这一点,

这是功能

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
}

任何想法我如何运行此功能测试???我很挣扎很多。

独立于原始问题,您不应为每个请求创建新的HTTP客户端。客户的维护池,应尽可能重复使用。

您可以解决此问题,并通过注入HTTP客户端继续使用现有的模拟服务器。

还请注意,问题中的接口定义与实现不符。这两个方法签名不是相同的:

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

选择一个。我可能会在此处使用非分子类型。大写字母缩写为GO(HTTPReq,而不是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.
}

由于服务结构已经具有REQ接口,在测试以满足REQ接口的模拟测试初始服务对象期间。像这样的东西
https://stackoverflow.com/a/53805535/3968921

最新更新