go - 如何模拟第二次尝试 http 调用?

标签 go mocking retrypolicy retry-logic http-mock

作为我第一个项目的一部分,我正在创建一个小型库来向任何用户发送短信。如果第一次没有收到肯定状态,我已经添加了等待和重试的逻辑。这是对短信发送服务的基本 HTTP 调用。我的算法看起来像这样(注释会解释代码的流程):

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 响应的功能。因此,我无法在第二次或第三次重试中测试是否成功。我可以在第一次测试中测试成功或完全失败。

是否有适合我测试此特定功能的需求的软件包?如果不是,我如何使用当前工具实现此目的?

最佳答案

这可以使用标准库中的测试服务器轻松实现 httptest package .通过对其中包含的示例稍作修改,您可以通过执行以下操作为您想要的每个响应设置函数:

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

关于go - 如何模拟第二次尝试 http 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50081104/

相关文章:

go - Go 中的方案解释器

python - 在Windows操作系统上使用Go和Python实现客户端-服务器模型

android - 是否有一种方法可以在使用 Espresso 测试的 Activity 中捕获调用的方法

Azure 服务总线 : transient errors (exceptions) received through the message pump with built-in retry policy. 为什么?

azure - 重试请求以 "Content length mismatch"结尾

windows - 如何打印到控制台窗口?

unit-testing - 如何模拟 HttpClientCertificate?

javascript - 您使用过哪些 JavaScript 单元测试和模拟框架?

go - 将重试策略变成可重用的函数

go - 递归结构反射错误 : panic: reflect: Field of non-struct type