Использование интерфейса для тестирования, как внедрение зависимости - PullRequest
0 голосов
/ 25 декабря 2018

Я использую следующий код, который работает нормально.

Это рабочий пример

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, что я пытаюсь, я изменил код для использования интерфейса, который работает.

Это просто пример, чтобы дать точку (реальный код гораздо сложнее)

Проблема, которую я не понимаю, как смоделировать функцию внутри 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()
        })
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...