[英]What is the most idiomatic way to emulating Perl's Test::More::done_testing?
[英]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)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.