当测试HTTP请求时出现Go空指针解引用错误。

huangapple go评论110阅读模式
英文:

Go Nil Dereference Error When Testing HTTP Request

问题

我正在尝试在我的Go库中测试一个HTTP请求。调用该请求的对象通过依赖注入接受一个HTTP客户端对象,所以在我的测试中,我像这样模拟了HTTP客户端:

  1. func TestMyObject(t *testing.T) {
  2. server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  3. w.WriteHeader(200)
  4. w.Header().Set("Content-Type", "application/json")
  5. fmt.Fprintln(w, mockJSONResponse)
  6. }))
  7. defer server.Close()
  8. // 创建一个传输对象,将所有流量重定向到示例服务器
  9. transport := &http.Transport{
  10. Proxy: func(req *http.Request) (*url.URL, error) {
  11. return url.Parse(server.URL)
  12. },
  13. }
  14. // 创建一个带有传输对象的http.Client
  15. httpClient := &http.Client{Transport: transport}
  16. // 将httpClient传递给我的对象
  17. }

这是在我的对象中进行HTTP请求的方式:

  1. // Make - 发送一个准备好的HTTP请求
  2. func (ir *MyObject) Make() *http.Response {
  3. if ir.Err != nil {
  4. return nil
  5. }
  6. ir.resp, ir.Err = ir.Client.Do(ir.req)
  7. runtime.SetFinalizer(ir, func(ir *MyObject) {
  8. ir.resp.Body.Close()
  9. })
  10. ir.logReqRes()
  11. ir.checkErrorResponse()
  12. return ir.resp
  13. }

然而,我得到了空指针解引用错误:

  1. panic: runtime error: invalid memory address or nil pointer dereference [recovered]
  2. panic: runtime error: invalid memory address or nil pointer dereference

在这个函数中(我试图记录响应):

  1. // 记录请求和响应
  2. func (ir *MyObject) logReqRes() {
  3. log.Print("AAAAAAA")
  4. log.Print(ir.resp)
  5. log.Print("AAAAAAA")
  6. if reqInfo, err := httputil.DumpRequest(ir.req, true); err == nil {
  7. log.Print("Logging request:")
  8. log.Print(string(reqInfo))
  9. }
  10. if respInfo, err := httputil.DumpResponse(ir.resp, true); err == nil {
  11. log.Print("Logging response:")
  12. log.Print(string(respInfo))
  13. }
  14. }

如你所见,ir.resp 为 nil,原因不明。有什么想法吗?

英文:

I am trying to test a HTTP request in my Go library. Object which makes the call accepts a HTTP client object via dependency injection so in my test I am mocking the HTTP client like this:

  1. func TestMyObject(t *testing.T) {
  2. server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  3. w.WriteHeader(200)
  4. w.Header().Set("Content-Type", "application/json")
  5. fmt.Fprintln(w, mockJSONResponse)
  6. }))
  7. defer server.Close()
  8. // Make a transport that reroutes all traffic to the example server
  9. transport := &http.Transport{
  10. Proxy: func(req *http.Request) (*url.URL, error) {
  11. return url.Parse(server.URL)
  12. },
  13. }
  14. // Make a http.Client with the transport
  15. httpClient := &http.Client{Transport: transport}
  16. // I am passing the httpClient to my object
  17. }

Here is how the HTTP request is made within my object:

  1. // Make - makes a prepared HTTP request
  2. func (ir *MyObject) Make() *http.Response {
  3. if ir.Err != nil {
  4. return nil
  5. }
  6. ir.resp, ir.Err = ir.Client.Do(ir.req)
  7. runtime.SetFinalizer(ir, func(ir *MyObject) {
  8. ir.resp.Body.Close()
  9. })
  10. ir.logReqRes()
  11. ir.checkErrorResponse()
  12. return ir.resp
  13. }

I am getting nil pointer dereference error though:

  1. panic: runtime error: invalid memory address or nil pointer dereference [recovered]
  2. panic: runtime error: invalid memory address or nil pointer dereference

In this function (I am trying to log the response):

  1. // Logs request and response
  2. func (ir *MyObject) logReqRes() {
  3. log.Print("AAAAAAA")
  4. log.Print(ir.resp)
  5. log.Print("AAAAAAA")
  6. if reqInfo, err := httputil.DumpRequest(ir.req, true); err == nil {
  7. log.Print("Logging request:")
  8. log.Print(string(reqInfo))
  9. }
  10. if respInfo, err := httputil.DumpResponse(ir.resp, true); err == nil {
  11. log.Print("Logging response:")
  12. log.Print(string(respInfo))
  13. }
  14. }

As you can see, ir.resp is nil for some reason. Any ideas?

答案1

得分: 0

好的,以下是翻译好的内容:

好的,我发现了一个问题。更好的错误日志显示实际上表明我的错误非常简单。

我将这个作为URL传递给了模拟的HTTP客户端:

  1. host/api/v1/tokens/

这导致了以下错误:

  1. Post host/api/v1/tokens/: 不支持的协议方案

显然,即使你正在使用一个测试服务器,URL也必须包含一个正确的HTTP协议方案(http://)。

英文:

Ok. I found an issue. Better logging of errors actually showed that my mistake was very simple.

I was passing this as a URL to mocked HTTP client:

  1. host/api/v1/tokens/

Which was resulting in this error:

  1. Post host/api/v1/tokens/: unsupported protocol scheme

Apparently the URL must include a proper HTTP scheme (http://) even when you are using a test server.

huangapple
  • 本文由 发表于 2015年4月20日 17:05:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/29743508.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定