使用接口进行测试,例如依赖注入

时间:2018-12-25 17:04:14

标签: unit-testing go dependency-injection

我使用下面的代码行得通。

这是可行的示例

https://play.golang.org/p/wjvJtDNvJAQ

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

type requester interface {
    HTTPRequest(c string, i string, mtd string, url string) (p []byte, e error)
}
type impl struct {
    client *http.Client
}

// ----This is the function which I need to mock
func (s *ServiceInfo) wrapperFN() {
    // Function 1 - get the values
    v1, v2 := s.json.parseJson()
    // call to http function
    s.req.HTTPRequest(v1, v2, "POST", "http://www.mocky.io/v2/5c20eccc2e00005c001e0c84")
}

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 parser interface {
    parseJson() (string, string)
}

type jsonP struct {
    data string
}

func (s jsonP) parseJson() (string, string) {
    var result map[string]interface{}
    json.Unmarshal([]byte(s.data), &result)
    b := result["person"].(map[string]interface{})
    for key, value := range b {
        return key, value.(string)
    }
    return "", ""
}

type ServiceInfo struct {
    req  requester
    json parser
}

// When in production pass in concrete implementations.
func NewServiceInfo(http requester, json parser) *ServiceInfo {
    return &ServiceInfo{
        req:  http,
        json: json,
    }
}

func main() {
    httpClient := http.Client{}
    js := `{"person":{"p1":"username","p2":"password"},"customers":"10"}`
    j := jsonP{data: js}
    s := NewServiceInfo(impl{client: &httpClient}, j)
    s.wrapperFN()
}

现在我想对其进行测试wrapperFN,我尝试将代码更改为使用interface,此方法有效。

这只是一个例子(实际代码要复杂得多)

在现实世界wrapperFN中,我不了解如何像parseJson()一样在warpperFN内部模拟函数的问题包含几个我需要模拟的函数,因为只是在测试将提供错误。

最好模拟parseJson()HTTPRequest之类的函数?并假设在wrapperFN内有其他不相关的功能...

我需要知道这是否是测试功能的最佳实践。

这是测试(不确定如何正确设置)

package main

import (
    "net/http"
    "net/http/httptest"
    "testing"
)

func TestServiceInfo_wrapperFN(t *testing.T) {
    tests := []struct {
        name string
        s    *ServiceInfo
    }{
        {
            name: "wrapper test",
            s:    &ServiceInfo{},
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {

            var testHandler http.Handler
            srv := httptest.NewServer(testHandler)
            defer srv.Close()
            iReq := &impl{
                client: srv.Client(),
            }
            v := &ServiceInfo{http: *iReq}
            v.wrapperFN()
        })
    }
}

0 个答案:

没有答案