英文:
Split function into 2 function for test coverage
问题
我应该如何测试ioutil.ReadAll(rep.Body)
的错误?我需要将我的函数分成两部分吗?一部分用于发起请求,另一部分用于读取响应体并返回字节和错误。
func fetchUrl(URL string) ([]byte, error) {
resp, err := http.Get(URL)
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return nil, err
}
return body, nil
}
英文:
How can I test the error for ioutil.ReadAll(rep.Body)
? Do I need to split my function in two, one which will make the request, and another one which will read the body and return the bytes and error?
func fetchUrl(URL string) ([]bytes, error) {
resp, err := http.Get(URL)
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return nil, err
}
return body, nil
}
答案1
得分: 2
基本上是的,除非你在测试时使用net/http/httptest
或类似的方式来模拟你的HTTP服务器。
但问题是:你真正要测试什么?是ioutil.ReadAll()
是否能检测到错误?但我确信这已经在Go标准库的测试套件中得到了覆盖。
因此,在这种特殊情况下,我认为你只是为了测试而测试。在我看来,对于这种琐碎的情况,更好的做法是集中精力处理获取到的结果。
英文:
Basically yes, unless you're using net/http/httptest
or a similar way to mock your HTTP server when testing.
But the question is: what would you really be testing? That ioutil.ReadAll()
detects errors? But I'm sure this was already covered by the test suite of the Go's stdlib.
Hence I'd say that in this particular case you're about to test for the testing's sake. IMO for such trivial cases it's better to concentrate on how the fetched result is further processed.
答案2
得分: 2
我需要将我的函数分成两部分吗?一个用于发送请求,另一个用于读取响应体并返回字节和错误信息?
第一个函数是http.Get
,第二个函数是ioutil.ReadAll
,所以我认为没有必要进行分割。你只是创建了一个使用两个其他函数的函数,假设这两个函数都能正常工作。你甚至可以简化你的函数,使其更加明显:
func fetchURL(URL string) ([]byte, error) {
resp, err := http.Get(URL)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return ioutil.ReadAll(resp.Body)
}
如果你想测试fetchURL
函数是否使用了http.Get
和ioutil.ReadAll
,我个人不会费心直接测试它,但如果你坚持要测试,你可以为单个测试覆盖http.DefaultTransport
,并提供自己的RoundTripper
,它返回具有某些错误场景的http.Response
(例如,在读取响应体时出现错误)。
以下是一个简要的示例:
type BrokenTransport struct {
}
func (*BrokenTransport) RoundTrip(*http.Request) (*http.Response, error) {
// 返回具有特定错误行为的 Response
}
http.DefaultTransport = &BrokenTransport{}
// 现在,http.Get将使用你的 RoundTripper。
// 在测试结束后,你应该恢复 http.DefaultTransport。
希望对你有帮助!
英文:
> Do I need to split my function in two, one which will make the request, and another one which will read the body and return the bytes and error?
The first one is called http.Get
and the other one ioutil.ReadAll
, so I don't think there's anything to split. You just created a function that uses two other functions together which you should assume are working correctly. You could even simplify your function to make it more obvious:
func fetchURL(URL string) ([]byte, error) {
resp, err := http.Get(URL)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return ioutil.ReadAll(resp.Body)
}
If you want to test anything is your fetchURL
function using http.Get
and ioutil.ReadAll
together. I wouldn't personally bother to test it directly, but if you insist on it, you can overwrite http.DefaultTransport
for a single test and provide your own, which returns http.Response
with body implementing some error scenarios (e.g. and error during body read).
Here is the sketch idea:
type BrokenTransport struct {
}
func (*BrokenTransport) RoundTrip(*http.Request) (*http.Response, error) {
// Return Response with Body implementing specific error behaviour
}
http.DefaultTransport = &BrokenTransport{}
// http.Get will now use your RoundTripper.
// You should probably restore http.DefaultTransport after the test.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论