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

I use the following code which works ok.

This is working example

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()
}

Now i want to test it wrapperFN , what I try I've changed the code to use interface , which works.

This is just example to give a point ( the real code much more complicated)

The problem that I dont understand how to mock function inside wrapperFN like parseJson() , in the real world warpperFN contains several function which I need to mock ,because just calling them in the test will provide error.

How it's best to mock function like parseJson() & HTTPRequest? and assume that inside wrapperFN there is additional functions which is not related...

I need to know if this is the best practice for testing function.

This is the test (which im not sure how to make it right)

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()
        })
    }
}