英文:
Golang Godog REST API Test fails
问题
过去两周我一直在研究GODOG,这是一个类似于Golang的黄瓜行为驱动开发(BDD)工具。我觉得它非常有趣,最近我花了更多时间编写我的REST API的测试。最近,我一直无法通过一个测试。这个测试涉及一个JSON结构,其中包含子JSON。我正在按照以下链接中的示例进行测试:
https://github.com/DATA-DOG/godog/tree/master/examples/api
我有一个结构体:
type Status struct {
ErrorCode string `json:"ERROR_CODE"`
ErrorText string `json:"ERROR_TEXT"`
}
type OutputResponse1 struct {
Status Status `json:"STATUS"`
}
type OutputResponse2 struct {
Status Status `json:"STATUS"`
Config json.RawMessage `json:"CONFIG"`
}
一个字节类型的变量:
var responseByte []byte
还有两种不同类型的输出响应:
//--------------1
responseByte, _ = json.Marshal(OutputResponse1{
Status: Status{
ErrorCode: "-2",
ErrorText: "Config was not found",
},
})
//------------2
responseByte, _ = json.Marshal(&OutputResponseSuccess{
Status: Status{
ErrorCode: "0",
ErrorText: "",
},
Config: json.RawMessage(body),
})
json.Rawmessage
是来自另一个源的内容,格式如下:
{
"binaryVersion": "1.0.0",
"configVersion": "1.1.1"
}
现在在功能文件中,我测试了以下内容:
//--------------1
并且响应应该匹配以下JSON:
{
"STATUS": {
"ERROR_CODE": "-2",
"ERROR_TEXT": "Config was not found"
}
}
这个测试通过了。
第二个测试涉及到了json.RawMessage
:
并且响应应该匹配以下JSON:
{
"STATUS": {
"ERROR_CODE": "0",
"ERROR_TEXT": " "
},
"CONFIG": {
"binaryVersion": "1.0.0",
"configVersion": "1.1.1"
}
}
这个测试失败了,尽管GODOG的输出与期望的完全相同。
------------------------GODOG测试的实际输出---------------------------
并且响应应该匹配以下JSON:
{"STATUS":{"ERROR_CODE":"0","ERROR_TEXT":" "},"CONFIG":{"binaryVersion":"1.0.0","configVersion":"1.1.1"}}
期望的JSON与实际的不匹配:
{"STATUS":{"ERROR_CODE":"0","ERROR_TEXT":" "},"CONFIG":{"binaryVersion":"1.0.0","configVersion":"1.1.1"}}
--- 失败的场景:
有人建议我去掉前导和尾随的空格,所以我尝试了:
bytes.TrimSpace(responseByte)
但还是没有成功。有人遇到同样的问题吗?
英文:
For past 2 weeks I have been looking into GODOG, a cucumber like bdd for golang. I found it very interesting and recently I am spending more time on writing a test for my REST API(s). Recently, I am continiuosly fialing to pass one of my test. This one includes a JSON struct that has childen JSON(s) inside itself. Also I am following exact example found at following link for my test:
https://github.com/DATA-DOG/godog/tree/master/examples/api
I have a struct like:
type Status struct {
ErrorCode string `json:"ERROR_CODE"`
ErrorText string `json:"ERROR_TEXT"`
}
type OutputResponse1 struct {
Status Status `json:"STATUS"`
}
type OutputResponse2 struct {
Status Status `json:"STATUS"`
Config json.RawMessage `json:"CONFIG"`
}
A byte type variable:
var responseByte []byte
And two different kind of output response:
//--------------1
responseByte, _ = json.Marshal(OutputResponse1{
Status: Status{
ErrorCode: "-2",
ErrorText: "Config was not found",
},
})
//------------2
responseByte, _ = json.Marshal(&OutputResponseSuccess{
Status: Status{
ErrorCode: "0",
ErrorText: " ",},
Config: json.RawMessage(body),
})
The json.Rawmessage
is something coming from another source which looks like:
{
"binaryVersion":"1.0.0",
"configVersion":"1.1.1"
}
Now in feature file I have tested out something like this:
//--------------1
And the response should match json:
{
"STATUS": {
"ERROR_CODE": "-2",
"ERROR_TEXT": "Config was not found"
}
}
THIS TEST PASS
The second one being one with json.RawMessage
And the response should match json:
{
"STATUS": {
"ERROR_CODE":"0",
"ERROR_TEXT":" "
},
"CONFIG":{
"binaryVersion":"1.0.0",
"configVersion":"1.1.1"
}
}
NOW THIS ONE FAILS, EVEN THOUGH THE GODG OUTPUT HAS THE ACTUAL AND EXPECTED SAME TO SAME
------------------------Acutal output of godog test---------------------------
And the response should match json:
{"STATUS":{"ERROR_CODE":"0","ERROR_TEXT":" "},"CONFIG": {"binaryVersion":"1.0.0","configVersion":"1.1.1"}}
Expected json does not match actual:
{"STATUS":{"ERROR_CODE":"0","ERROR_TEXT":" "},"CONFIG": {"binaryVersion":"1.0.0","configVersion":"1.1.1"}}
--- Failed scenarios:
Someone from the godog also advised me to get rid of leading and trailing whitespace, so I even did
bytes.TrimSpace(responseByte)
still no luck.
Anyone facing the same problem?
答案1
得分: 1
不确定这是否能解决你的问题,但如果你使用的是Go1.7或更低版本,可以尝试将Config
字段的类型设置为*json.RawMessage
。因为在Go 1.8之前,json.RawMessage
的MarshaJSON
方法是在指针接收器上定义的,而不是值接收器,这导致json.RawMessage
的值被编码为Base64字符串字节。
type OutputResponse2 struct {
Status Status `json:"STATUS"`
Config *json.RawMessage `json:"CONFIG"`
}
raw := json.RawMessage(body)
responseByte, err := json.Marshal(&OutputResponseSuccess{
Status: Status{
ErrorCode: "0",
ErrorText: " ",
},
Config: &raw,
})
if err != nil {
// ...
}
英文:
Not sure if this will solve your issue, but if you're on Go1.7 or less then try using *json.RawMessage
as the Config
field's type. Because Go's pre 1.8 json.RawMessage
had its MarshaJSON
method defined on the pointer receiver as opposed to the value receiver which caused json.RawMessage
values to be encoded as strings bytes in base64.
type OutputResponse2 struct {
Status Status `json:"STATUS"`
Config *json.RawMessage `json:"CONFIG"`
}
raw := json.RawMessage(body)
responseByte, err := json.Marshal(&OutputResponseSuccess{
Status: Status{
ErrorCode: "0",
ErrorText: " ",
},
Config: &raw,
})
if err != nil {
// ...
}
答案2
得分: 1
我是godog的作者。在你提供的示例中,它逐个比较字节并打印出实际结果,直到最后一个匹配的字节。
现在来说说Go语言中的json.Marshal。当它将一个map编组为json时,它会对map键进行排序。有了这个认识,如果我们重新编码预期和实际的json响应,那么我们可以确保如果匹配的话,它应该产生相同的字节切片,无论你以什么顺序放置预期的对象键。
英文:
I'm the author of godog. Currently in the example you linked, it compares bytes one by one and prints the actual result up to the last byte it matched.
Now about the json.Marshal in go. When it marshals a map to json, it sorts map keys and having that in mind if we re-encode both expected and actual json responses, then we can be certain that it should produce the same byte slice if it matches, no matter in which order you placed expected object keys.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论