在Golang中对HTTP JSON响应进行单元测试

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

Unit testing http json response in Golang

问题

我正在使用gin作为我的HTTP服务器,并将一个空数组作为JSON响应发送回去:

  1. c.JSON(http.StatusOK, []string{})

我得到的JSON字符串是"[]\n"。换行符是由JSON编码器对象添加的,可以在这里查看。

使用goconvey,我可以像这样测试我的JSON:

  1. 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:

  1. 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

  1. 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

你应该首先将响应的主体解组为一个结构体,然后与生成的对象进行比较。示例代码如下:

  1. result := []string{}
  2. if err := json.NewDecoder(response.Body).Decode(&result); err != nil {
  3. log.Fatalln(err)
  4. }
  5. So(len(result), ShouldEqual, 0)
英文:

You should first unmarshal the body of the response into a struct and compare against the resulting object. Example:

  1. result := []string{}
  2. if err := json.NewDecoder(response.Body).Decode(&result); err != nil {
  3. log.Fatalln(err)
  4. }
  5. 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 字符串在语义上等价。

在你的情况下:

  1. // 空格会被忽略,不需要 \n
  2. 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:

  1. // white space is ignored, no need for \n
  2. 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

我这样做是因为我不想包含额外的库。

  1. tc := testCase{
  2. w: httptest.NewRecorder(),
  3. wantResponse: mustJson(t, map[string]string{"message": "unauthorized"}),
  4. }
  5. ...
  6. if tc.wantResponse != tc.w.Body.String() {
  7. t.Errorf("want %s, got %s", tt.wantResponse, tt.w.Body.String())
  8. }
  9. ...
  10. func mustJson(t *testing.T, v interface{}) string {
  11. t.Helper()
  12. out, err := json.Marshal(v)
  13. if err != nil {
  14. t.Fatal(err)
  15. }
  16. return string(out)
  17. }
英文:

I made it this way. Because I don't want to include an extra library.

  1. tc := testCase{
  2. w: httptest.NewRecorder(),
  3. wantResponse: mustJson(t, map[string]string{"message": "unauthorized"}),
  4. }
  5. ...
  6. if tc.wantResponse != tc.w.Body.String() {
  7. t.Errorf("want %s, got %s", tt.wantResponse, tt.w.Body.String())
  8. }
  9. ...
  10. func mustJson(t *testing.T, v interface{}) string {
  11. t.Helper()
  12. out, err := json.Marshal(v)
  13. if err != nil {
  14. t.Fatal(err)
  15. }
  16. return string(out)
  17. }

huangapple
  • 本文由 发表于 2015年11月12日 04:32:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/33659298.html
匿名

发表评论

匿名网友

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

确定