Инъекция зависимости в Голанг - PullRequest
0 голосов
/ 19 января 2019

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

  1. вызов функции getData, которая предоставляет вам данные для выполнения http-запроса
  2. используйте вывод функции getData для выполнения http-запроса.

Раньше это работало, но теперь я хочу сделать для него модульное тестирование, и я прочитал несколько блогов, как сделать эту работу, и кажется, что внедрение зависимостей является ключом для этого. Я пытался подписаться на этот пост .

Я пытаюсь принять код, но не уверен, правильно ли я это сделал.

Идея состоит в том, чтобы использовать функцию getData в prod с некоторым URL-адресом для выполнения, а в unit test предоставить другой URL-адрес, аналогичный httptest.NewServer(testHandler) Как я должен сделать это прямо в 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

Чтобы заставить это работать, это не проблема , но проблема здесь, чтобы заставить его проверяемый код

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

1 Ответ

0 голосов
/ 22 января 2019

Я использовал 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

Затем используйте эту фиктивную реализацию при написании юнит-тестов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...