簡體   English   中英

在 Go 中使用 HTTP 請求測試功能的最慣用方法是什么?

[英]What's the most idiomatic way of testing functions with HTTP requests in Go?

我有一個有趣的小天氣應用程序。 只需 99 美元/天,該應用程序就會每天檢查天氣,如果西雅圖下雨,就給聖地亞哥的人們送一把雨傘。

我將這兩個函數用作我的應用程序的一部分:

func IsRaining() (bool, error) {
    resp, err := http.Get("https://isitraining.in/Seattle")
    if err != nil {
        return false, fmt.Errorf("could not fetch raining status: %w", err)
    }

    parsed, err := weather.Parse(resp)
    if err != nil {
        return false, fmt.Errorf("could not parse the weather: %w", err)
    }

    return parsed.IsRaining, nil
}

func SendUmbrella() error {
    postData := umbrellaPostData()
    resp, err := http.Post("https://amazon.com", "text/html", &postData)
    if err != nil {
        return fmt.Errorf("could not send umbrella: %w", err)
    }
    return nil
}

我想測試IsRaining()SendUmbrella() ,但我不想在每次運行測試時都給某人送傘; 我的工程師使用 TDD,我確實有預算,你知道的。 IsRaining()相同,如果互聯網中斷了怎么辦? 我仍然需要能夠通過測試運行,風雨無阻。

我想以這樣一種方式來做到這一點,即代碼保持符合人體工程學和可讀性,但我絕對需要能夠測試那些依賴於 HTTP 的函數。 在 Go 中最慣用的方法是什么?

PS我正在使用Testify 在評論中告訴我所有關於我如何失去慣用 Go 的任何希望:)

我不知道“最慣用的”,但與任何其他語言一樣,硬編碼 包令人頭疼。 不要直接在 http package 上調用方法,而是創建一個 httpClient 接口。 然后模擬 httpClient 接口。

您可以將 httpClient 傳遞給 function,但將這些轉換為結構上的方法更有意義。

// Set up an interface for your http client, same as http.Client.
type httpClient interface {
    Get(string) (*http.Response, error)
}

// Make a struct to hang the client and methods off of.
type umbrellaGiver struct {
    client httpClient
}

// A cut down example method.
func (giver umbrellaGiver) getExample() ([]byte, error) {
    resp, err := giver.client.Get("https://example.com")
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    return io.ReadAll(resp.Body)
}

然后可以將一個模擬的 httpClient 放入您的雨傘提供者中。

// Our mocked client.
type mockedClient struct {
    mock.Mock
}

// Define the basic mocked Get method to record its arguments and
// return its mocked values.
func (m mockedClient) Get(url string) (*http.Response, error) {
    args := m.Called(url)
    if args.Get(0) == nil {
        return nil, args.Error(1)
    } else {
        return args.Get(0).(*http.Response), args.Error(1)
    }
}

func main() {
    // Make a mockedClient and set up an expectation.
    client := new(mockedClient)

    // Make an umbrellaGiver which uses the mocked client.
    s := umbrellaGiver { client: client }

    // Let's test what happens when the call fails.
    client.On(
        "Get", "https://example.com",
    ).Return(
        nil, errors.New("The system is down"),
    )

    body, err := s.getExample()
    if err != nil {
        panic(err)
    }
    fmt.Printf("%s", body)
}

請參閱Golang 中的 Mocking HTTP 請求

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM