Search code examples
gogo-testing

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


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() ?


Solution

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