Как смоделировать вторую попытку http-вызова?
В рамках моего первого проекта я создаю крошечную библиотеку для отправки 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 по отдельности. Поэтому я не могу проверить успех во второй или третьей повторной попытке. Я могу либо проверить успех в первый раз, либо провал вообще.
Есть ли пакет, который соответствует моим потребностям тестирования этой конкретной функции? Если нет, как я могу добиться этого с помощью современных инструментов?
2 ответа
Этого легко достичь с помощью тестового сервера, входящего в стандартный пакет 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
Исполняемый код здесь:
Не уверен, что вам все еще нужен ответ, но github.com/jarcoal/httpmock предоставляет способ сделать это с помощью ResponderFromMultipleResponses .