Тестовая функция переноса с внедрением зависимости - PullRequest
0 голосов
/ 20 декабря 2018

У меня есть эта функция, которую мне нужно смоделировать в тесте, я смогла смоделировать ее, как и ожидалось, с помощью пакета http mock, но теперь у меня есть функция, которая вызывает метод HttpReq, и здесь я не могу использовать http mockпакет, который я прочитал о внедрении зависимостей и попробовал что-то, но я не смог сделать это полностью,

Это функция

type params struct {
    cs     string
    ci     string
    method string
    url    string
}

// I added this struct but not sure if it's needed ... probably for test purpose but not sure how to use it.

type Impl struct {
 client *http.Client
}

func (i *Impl) HttpReq(p *params) ([]byte, error) {
    httpClient := i.client
    req, err := http.NewRequest(p.method, p.url, nil)
    if err != nil {
        fmt.Sprintf(err)
    }
    req.SetBasicAuth(p.cs, p.ci)
    res, err := httpClient.Do(req)
    if err != nil {
        fmt.Sprintf(err)
    }
    t, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.Sprintf(err)
    }
    defer res.Body.Close()
    return t, nil
}

Это то, что я пытался

Я создал интерфейс

type Req interface {
    HttpReq(params) ([]byte, error)
}

Теперь я создал структуру, которая содержит интерфейс

type Service struct {
    req Req
}

Это функция, которую мне нужно проверить

func (c *Service) execute(cli Connection , args []string) (error, []byte) {
    sk, err := c.doSomthing(cli, args)

    sc, err := c.doSometing2(serviceK, []string{"url", "cl", "ct"})

    cc := strings.Fields(serviceCredentials)

    // ----------Here is what I need to mock ----------
    t, err := c.req.HttpReq(params{cs: cc[1],
        ci:     cc[2],
        method: http.MethodPost,
        url:    cc[0],})
    return err, t
}

Любая идея, как я могу запустить тест для этой функции ???Я много с этим борюсь.

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

Независимо от исходного вопроса, вы не должны создавать новых клиентов HTTP для каждого запроса.Клиент поддерживает пул соединений, и его следует использовать как можно чаще.

Вы можете это исправить и продолжить использовать существующий фиктивный сервер, введя HTTP-клиент.

Обратите внимание также на то, что определение интерфейсав вопросе не соответствует реализации.Эти две сигнатуры методов не совпадают:

HttpReq(params) ([]byte, error)  // Req
HttpReq(*params) ([]byte, error) // Impl

Выберите одну.Я бы, наверное, пошел с не указателем типа здесь. И инициалы в верхнем регистре идиоматические в Go (HTTPReq, а не HttpReq).

Добавьте клиента к типу Impl и используйте его в HTTPReq:

type Impl struct {
    client *http.Client
}

func (i *Impl) HTTPReq(p params) ([]byte, error) {
    req, err := http.NewRequest(p.method, p.url, nil)
    if err != nil {
        return nil, err
    }
    req.SetBasicAuth(p.cs, p.ci)

    res, err := i.client.Do(req)
    if err != nil {
        return nil, err
    }
    defer res.Body.Close()

    return ioutil.ReadAll(res.Body)
}

Тип службы не должен изменяться.

В тестах просто введите тестового клиента в значение Impl:

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

func TestService_execute(t *testing.T) {
    var testHandler http.Handler // TODO

    srv := httptest.NewServer(testHandler)
    defer srv.Close()

    client := srv.Client()
    tp := client.Transport.(*http.Transport)

    // Direct all requests to the test server, no matter what the request URL is.
    tp.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
        // Note that we ignore the network and addr parameters, since these are 
        // derived from the request URL and are unrelated to the test server.

        srvAddr := srv.Listener.Addr()
        return (&net.Dialer{}).DialContext(ctx, srvAddr.Network(), srvAddr.String())
    }

    svc := &Service{
        req: &Impl{
            client: client,
        },
    }

    svc.execute(/* ... */)

    // assert request, response, etc.
}
0 голосов
/ 20 декабря 2018

Поскольку структура Service уже имеет интерфейс req, во время тестов инициализируйте объект службы с mock, который удовлетворяет интерфейсу req.Как то так
https://stackoverflow.com/a/53805535/3968921

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