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

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

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)
}

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:

确定