Как смоделировать вторую попытку http-вызова? - PullRequest
0 голосов
/ 29 апреля 2018

В рамках моего первого проекта я создаю крошечную библиотеку для отправки SMS любому пользователю. Я добавил логику ожидания и повторных попыток, если он не получает положительный статус при первом запуске. Это простой HTTP-вызов для отправки SMS. Мой алгоритм выглядит следующим образом (комментарии объясняют поток кода):

for {
    //send request
    resp, err := HTTPClient.Do(req)
    checkOK, checkSuccessUrl, checkErr := CheckSuccessStatus(resp, err)

    //if successful don't continue
    if !checkOK and checkErr != nil {
        err = checkErr
        return resp, SUCCESS, int8(RetryMax-remain+1), err
    }

    remain := remain - 1
    if remain == 0 {
        break
    }

    //calculate wait time
    wait := Backoff(RetryWaitMin, RetryWaitMax, RetryMax-remain, resp)
    //wait for time calculated in backoff above
    time.Sleep(wait)

    //check the status of last call, if unsuccessful then continue the loop

    if checkSuccessUrl != "" {
        req, err := GetNotificationStatusCheckRequest(checkSuccessUrl)
        resp, err := HTTPClient.Do(req)
        checkOK, _, checkErr = CheckSuccessStatusBeforeRetry(resp, err)
        if !checkOK {

            if checkErr != nil {
                err = checkErr
            }
            return resp,SUCCESS, int8(RetryMax-remain), err
        }
    }
}

Теперь я хочу проверить эту логику с использованием любой доступной среды HTTP-макета. Лучшее, что у меня есть https://github.com/jarcoal/httpmock

Но этот не обеспечивает функциональность для раздельного ответа на первый и второй URL. Поэтому я не могу проверить успех во второй или третьей повторной попытке. Я могу либо проверить успех в первый раз, либо провал вообще.

Существует ли какой-либо пакет, который соответствует моим потребностям тестирования этой конкретной функции? Если нет, как я могу добиться этого с помощью текущих инструментов?

1 Ответ

0 голосов
/ 29 апреля 2018

Этого легко достичь, используя тестовый сервер, входящий в стандартную библиотеку httptest . С небольшим изменением приведенного в нем примера вы можете настроить функции для каждого из желаемых ответов, выполнив следующее:

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/http/httptest"
)

func main() {
    responseCounter := 0
    responses := []func(w http.ResponseWriter, r *http.Request){
        func(w http.ResponseWriter, r *http.Request) {
            fmt.Fprintln(w, "First response")
        },
        func(w http.ResponseWriter, r *http.Request) {
            fmt.Fprintln(w, "Second response")
        },
    }
    ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        responses[responseCounter](w, r)
        responseCounter++
    }))
    defer ts.Close()

    printBody(ts.URL)
    printBody(ts.URL)
}

func printBody(url string) {
    res, err := http.Get(url)
    if err != nil {
        log.Fatal(err)
    }
    resBody, err := ioutil.ReadAll(res.Body)
    res.Body.Close()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%s", resBody)
}

Какие выходы:

First response
Second response

Исполняемый код здесь:

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

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