我有以前的代码,其工作方式如下:
- 调用函数
getData
,该函数为您提供执行http请求的数据- 使用
getData
函数输出执行http请求。
这是以前可行的方法,但是现在我想对其进行单元测试,并且我读了一些博客以了解如何实现此功能,并且依赖注入似乎是实现此目的的关键。我试图关注this post。
我尝试采用该代码,但不确定我是否做对了。
想法是在产品中使用getData
函数并执行一些url,并在unit test
中提供与httptest.NewServer(testHandler)
类似的不同url
如何在Go中正确设置?
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
type requester interface {
HTTPRequest(c string, i string, mtd string, url string) (p []byte, e error)
}
func (i impl) HTTPRequest(c string, ci string, mtd string, url string) (p []byte, e error) {
req, err := http.NewRequest(mtd, url, nil)
if err != nil {
return nil, err
}
req.SetBasicAuth(c, ci)
res, err := i.client.Do(req)
if err != nil {
return nil, err
}
token, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
defer res.Body.Close()
fmt.Println("success")
return token, nil
}
type iData interface {
getData() []string
}
type reqData struct {
f1 string
f2 string
}
func (s reqData) getData() []string {
a := make([]string, 4)
a[2] = "http://www.mocky.io/v2/5c20eccc2e00005c001e0c84"
a[3] = "/oauth/token?grant_type=client_credentials"
return a
}
type ServiceInfo struct {
req requester
data iData
}
type impl struct {
client *http.Client
}
func NewServiceInfo(http requester, data iData) *ServiceInfo {
return &ServiceInfo{
req: http,
data: data,
}
}
// ----This is the function which I need to mock
func (s *ServiceInfo) caller() {
// Function 1 - get the values
reqdata := s.data.getData()
// Function 2 -call to http function
s.req.HTTPRequest(reqdata[0], reqdata[1], "POST", reqdata[2])
}
func main() {
// not sure how to run it
//httpClient := http.Client{}
//d := reqData{f1: "user", f2: "password"}
//s := NewServiceInfo(impl{client: &httpClient}, d.getData())
//s.caller()
}
测试看起来像这样,但是真的不确定如何使它工作
It("Test", func() {
// Mock http call
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
u, p, ok := r.BasicAuth()
Ω(ok).Should(Equal(true))
Ω(u).Should(Equal("user"))
Ω(p).Should(Equal("password"))
}))
var httpClient = http.Client{}
si := NewServiceInfo(client{httpClient: &httpClient, url: server.URL})
t, err := si.r.httpReq("user", "password", http.MethodPost)
Ω(token).Should(Equal(string(t)))
Ω(err).ShouldNot(HaveOccurred())
})
该代码只是我完整代码的示例,因此我尝试使用它并仅放入相关部分
更新 使其更加清晰:)
我需要的是如何模拟(正确的方法)功能getData
,
提供产品代码中的url x
和测试中的url y
,这里我需要对功能caller
进行单元测试的细微差别
要使其起作用,这不是问题,但要使其成为可测试代码
答案 0 :(得分:0)
我一直在使用https://github.com/facebookgo/inject进行DI和https://github.com/golang/mock进行模拟。 例如:
// some_entity_dao.go
type SomeEntity interface {
Find(ctx context.Context, condition *model.SomeEntity) (*model.SomeEntity, error)
FindAll(ctx context.Context, condition *model.SomeEntity) ([]*model.SomeEntity, error)
Save(ctx context.Context, data *model.SomeEntity) error
Update(ctx context.Context, condition *model.SomeEntity, data *model.SomeEntity) error
Delete(ctx context.Context, condition *model.SomeEntity) error
}
并使用以下命令生成模拟实现:
//go:generate mockgen -source=./some_entity_dao.go -destination=./some_entity_dao_mock_impl.go -package dao
然后在编写单元测试时使用此模拟实现。