如何在Go测试用例中处理JSON语法错误?

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

How to handle json syntax error in a go test case?

问题

我正在测试一个场景,其中json.Unmarshal失败并返回

&json.SyntaxError{msg:"unexpected end of JSON input", Offset:0}

代码如下:

err = json.Unmarshal(input, &data)

if err != nil {
    return nil, err
}

测试用例期望这种类型的错误:

{
...
errorType: &json.SyntaxError{},
...
}

断言如下:

assert.Equal(t, tt.errorType, err)

但是失败了,因为错误消息不同:

expected: &json.SyntaxError{msg:"", Offset:0}
actual  : &json.SyntaxError{msg:"unexpected end of JSON input", Offset:0}

我该如何处理?也许可以利用Error()方法来处理?

英文:

I'm testing a scenario where json.Unmarshall fails and returns

&json.SyntaxError{msg:"unexpected end of JSON input", Offset:0}

the code is like this:

err = json.Unmarshal(input, &data)

if err != nil {
	return nil, err
}

test case is expecting this type of error:

{
...
errorType: &json.SyntaxError{},
...
}

the assertion is like this:

assert.Equal(t, tt.errorType, err)

which is failing because the error message is different:

expected: &json.SyntaxError{msg:"", Offset:0}
actual  : &json.SyntaxError{msg:"unexpected end of JSON input", Offset:0}

How can I handle this? Perhaps making use of Error() ?

答案1

得分: 4

首先,直接创建这个 sentinel 错误是不可能的:

_ = &json.SyntaxError{msg: "unexpected end of JSON input", Offset: 0}  // msg field is not exported

你能做的最接近的方法是检查错误的 类型。可以使用 errors.As 来实现:

var tt *json.SyntaxError

if errors.As(err, &tt) {
    log.Printf("Syntax Error: %v", tt)
} else if err != nil {
    log.Fatalf("Fatal: %#v", err)
}

你可以检查 Offset 字段,因为它是公开的。但是要比较非公开的 msg 字段,你需要使用 err.Error(),但这可能不太稳定,因为随着时间的推移,文本可能会发生变化。


注意: 在这里无法使用 errors.Is,因为它只测试错误的相等性:直接相等,或通过 error.Unwrap 进行嵌套。

由于这里的 json.SyntaxError 既不是被包装的,也不是 sentinel 错误,所以无法通过 errors.Is 进行匹配。

英文:

Firstly it's not possible to craft this sentinel error directly:

_ = &json.SyntaxError{msg: "unexpected end of JSON input", Offset: 0}  // msg field is not exported

the closest you can come is to check for the error type. To do this use errors.As

var tt *json.SyntaxError

if errors.As(err, &tt) {
	log.Printf("Syntax Error: %v", tt)
} else if err != nil {
	log.Fatalf("Fatal: %#v", err)
}

https://go.dev/play/p/mlqGN2ypwBs

You can check the Offset as that is public field. But to compare the non-public msg field, you'd need to use err.Error() - but this may be brittle as wording may change over time.


Note: errors.Is cannot be used here, as it only tests error equality: directly; or via error.Unwrap-ing.

Since the json.SyntaxError here is not wrapped - nor is it a sentinel error - it cannot be matched via errors.Is.

huangapple
  • 本文由 发表于 2022年4月6日 22:41:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/71768824.html
匿名

发表评论

匿名网友

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

确定