我有这个功能需要在测试中进行模拟,
我可以使用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
}
任何想法我如何可以对此功能进行测试???我为此苦苦挣扎。
答案 0 :(得分:2)
与原始问题无关,您不应为每个请求创建新的HTTP客户端。客户端维护一个连接池,应尽可能重用。
您可以修复该问题,并通过注入HTTP客户端来继续使用现有的模拟服务器。
还请注意,问题中的接口定义与实现不匹配。这两个方法签名不相同:
HttpReq(params) ([]byte, error) // Req
HttpReq(*params) ([]byte, error) // Impl
选择一个。我可能会在这里使用非指针类型。 And upper case initials are idiomatic in 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.
}
答案 1 :(得分:1)
由于Service结构已经具有req接口,因此在测试过程中,使用满足req接口的模拟初始化服务对象。
这样的东西
https://stackoverflow.com/a/53805535/3968921