英文:
Unit testing http json response in Golang
问题
我正在使用gin
作为我的HTTP服务器,并将一个空数组作为JSON响应发送回去:
c.JSON(http.StatusOK, []string{})
我得到的JSON字符串是"[]\n"
。换行符是由JSON编码器对象添加的,可以在这里查看。
使用goconvey
,我可以像这样测试我的JSON:
So(response.Body.String(), ShouldEqual, "[]\n")
但是,有没有更好的方法来生成预期的JSON字符串,而不仅仅是在它们后面添加一个换行符呢?
英文:
I am using gin
as my http server and sending back an empty array in json as my response:
c.JSON(http.StatusOK, []string{})
The resulting json string I get is "[]\n"
. The newline is added by the json Encoder object, see here.
Using goconvey
, I could test my json like
So(response.Body.String(), ShouldEqual, "[]\n")
But is there a better way to generate the expected json string than just adding a newline to all of them?
答案1
得分: 5
你应该首先将响应的主体解组为一个结构体,然后与生成的对象进行比较。示例代码如下:
result := []string{}
if err := json.NewDecoder(response.Body).Decode(&result); err != nil {
log.Fatalln(err)
}
So(len(result), ShouldEqual, 0)
英文:
You should first unmarshal the body of the response into a struct and compare against the resulting object. Example:
result := []string{}
if err := json.NewDecoder(response.Body).Decode(&result); err != nil {
log.Fatalln(err)
}
So(len(result), ShouldEqual, 0)
答案2
得分: 2
将请求体解析为结构体,然后使用Gocheck的DeepEquals函数进行比较。
https://godoc.org/launchpad.net/gocheck
英文:
Unmarshal the body into a struct and the use Gocheck's DeepEquals
https://godoc.org/launchpad.net/gocheck
答案3
得分: 2
你可能会发现 jsonassert 很有用。
它没有依赖于标准库之外的任何内容,并且允许你验证 JSON 字符串是否与你期望的 JSON 字符串在语义上等价。
在你的情况下:
// 空格会被忽略,不需要 \n
jsonassert.New(t).Assertf(response.Body().String(), "[]")
它可以处理任何形式的 JSON,并且提供非常友好的断言错误消息。
免责声明:我编写了这个包。
英文:
You may find jsonassert useful.
It has no dependencies outside the standard library and allows you to verify that JSON strings are semantically equivalent to a JSON string you expect.
In your case:
// white space is ignored, no need for \n
jsonassert.New(t).Assertf(response.Body().String(), "[]")
It can handle any form of JSON, and has very friendly assertion error messages.
Disclaimer: I wrote this package.
答案4
得分: 0
我这样做是因为我不想包含额外的库。
tc := testCase{
w: httptest.NewRecorder(),
wantResponse: mustJson(t, map[string]string{"message": "unauthorized"}),
}
...
if tc.wantResponse != tc.w.Body.String() {
t.Errorf("want %s, got %s", tt.wantResponse, tt.w.Body.String())
}
...
func mustJson(t *testing.T, v interface{}) string {
t.Helper()
out, err := json.Marshal(v)
if err != nil {
t.Fatal(err)
}
return string(out)
}
英文:
I made it this way. Because I don't want to include an extra library.
tc := testCase{
w: httptest.NewRecorder(),
wantResponse: mustJson(t, map[string]string{"message": "unauthorized"}),
}
...
if tc.wantResponse != tc.w.Body.String() {
t.Errorf("want %s, got %s", tt.wantResponse, tt.w.Body.String())
}
...
func mustJson(t *testing.T, v interface{}) string {
t.Helper()
out, err := json.Marshal(v)
if err != nil {
t.Fatal(err)
}
return string(out)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论