英文:
Why does this GoLang Mock HTTP responder return the wrong number of times it was called?
问题
我正在为我的Go应用程序编写测试用例,该应用程序进行HTTP请求。为了模拟来自远程主机的响应,我创建了这个stringProducer
类。
type stringProducer struct {
strings []string
callCount int
}
func (s *stringProducer) GetNext() string {
if s.callCount >= len(s.strings) {
panic("ran out of responses")
}
s.callCount++
fmt.Println("s.CallCount =", s.callCount)
return s.strings[s.callCount-1]
}
func mockHTTPResponder(producer stringProducer) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte(producer.GetNext()))
})
}
以下是我在main
函数中调用它的方式:
func main() {
producer := stringProducer{
strings: []string{"Hello World!"},
}
srv := httptest.NewServer(mockHTTPResponder(producer))
if producer.callCount != 0 {
panic("callCount is not 0")
}
var buf io.ReadWriter
req, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, fmt.Sprintf("%s/path/to/something", srv.URL), buf)
newClient := http.Client{}
newClient.Do(req)
if producer.callCount != 1 {
panic("callCount is not 1")
}
}
在这段代码中,当发起HTTP请求时,它会发送到上面的响应器,响应器会返回预先指定的文本。它还会将计数器stringProducer.callCount
增加1。
从下面的程序输出中,你可以看到它打印了一行显示callCount
增加到1的信息。然而,当我检查相同的值时,它不是1,而是0。为什么?如何修复这个问题?
s.CallCount = 1
panic: callCount is not 1
goroutine 1 [running]:
main.main()
/tmp/sandbox3935766212/prog.go:50 +0x118
Go Playground链接在这里:https://play.golang.org/p/mkiJAfrMdCw
英文:
I'm writing test cases for my Go application that makes HTTP requests.
To simulate a response from the remote host, I have created this class stringProducer
type stringProducer struct {
strings []string
callCount int
}
func (s *stringProducer) GetNext() string {
if s.callCount >= len(s.strings) {
panic("ran out of responses")
}
s.callCount++
fmt.Println("s.CallCount = ", s.callCount)
return s.strings[s.callCount-1]
}
func mockHTTPResponder(producer stringProducer) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte(producer.GetNext()))
})
}
Here is how I call it in my main function:
func main() {
producer := stringProducer{
strings: []string{"Hello World!"},
}
srv := httptest.NewServer(mockHTTPResponder(producer))
if producer.callCount != 0 {
panic("callCount is not 0")
}
var buf io.ReadWriter
req, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, fmt.Sprintf("%s/path/to/something", srv.URL), buf)
newClient := http.Client{}
newClient.Do(req)
if producer.callCount != 1 {
panic("callCount is not 1")
}
}
In this code, when an HTTP request is made, it goes to the responder above which responds with some pre-specified text. It also causes the counter stringProducer.callCount
to be incremented by 1.
From the program's output below, you can see that it prints a line showing that callCount was incremented to 1. However, when I check that same value, it is not 1. It is zero. Why? And how to fix that?
s.CallCount = 1
panic: callCount is not 1
goroutine 1 [running]:
main.main()
/tmp/sandbox3935766212/prog.go:50 +0x118
Go Playground link here: https://play.golang.org/p/mkiJAfrMdCw
答案1
得分: 2
你在mockHTTPResponder中通过值传递了stringProducer。这样做会得到mockHTTPResponder内部变量的副本。所有后续的更改都是在该副本上进行的(原始的stringProducer保持不变):
func mockHTTPResponder(producer stringProducer) http.Handler { // <- producer是原始变量的副本
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte(producer.GetNext())) // <- 在副本上进行s.callCount++操作
})
}
在mockHTTPResponder中传递一个指针。
英文:
You pass by value stringProducer in mockHTTPResponder. When you do this you get a copy of the variable inside mockHTTPResponder. And all the following changes are made on that copy (original stringProducer are left unchanged):
func mockHTTPResponder(producer stringProducer) http.Handler { // <- producer is a copy of the original variable
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte(producer.GetNext())) // <- s.callCount++ on the copy
})
}
Pass a pointer inside mockHTTPResponder.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论