Home > Back-end >  How to write unit test failure for json.NewDecoder.Decode?
How to write unit test failure for json.NewDecoder.Decode?

Time:11-04

I have to write unit tests for a function and this function uses json.NewDecoder.Decode

var infos models.RegisterInfos // struct with json fields
err := json.NewDecoder(r.Body).Decode(&infos)
if err != nil {
    // do something
}

How can I simulate an error in a unit test (using the testing package) for json.NewDecoder(r.Body).Decode(&infos) ? I tried looking in the NewDecoder and Decode source code but I couldn't find anything that can generate an error in just a few lines.

CodePudding user response:

you could send a body like <invalid json> as example:

func main() {
    body := "<invalid json>"
    var infos RegisterInfos // struct with json fields
    err := json.NewDecoder(strings.NewReader(body)).Decode(&infos)
    if err != nil {
        fmt.Println(err)
    }
}

See https://go.dev/play/p/44E99D0eQou

CodePudding user response:

Feed it an invalid input, or decode into an invalid output:

package main

import (
    "encoding/json"
    "fmt"
    "strings"
    "testing"
)

type Message struct {
    Name string
}

func TestDecodeFail(t *testing.T) {
    for _, tc := range []struct {
        in   string
        desc string
        out  any
    }{
        {`{Name: "Bobby"}`, "key without quotes", &Message{}},
        {`{"Name": "Foo"a}`, "extra character", &Message{}},
        {`{"Name": "Foo"}`, "bad destination", &struct{ Name int64 }{}},
        {`{"Name": "Foo`   "\u001a"   `"}`, "invalid character", &Message{}},
        {`{"Name": "Foo"}`, "unmarshal to nil", (*Message)(nil)},
    } {
        err := decode(tc.in, tc.out)
        if err != nil {
            fmt.Printf("%s -> %s, %T\n", tc.desc, err.Error(), err)
        }
    }
}

func decode(in string, out any) error {
    return json.NewDecoder(strings.NewReader(in)).Decode(out)
}

Outputs:

key without quotes -> invalid character 'N' looking for beginning of object key string, *json.SyntaxError
extra character -> invalid character 'a' after object key:value pair, *json.SyntaxError
bad destination -> json: cannot unmarshal string into Go struct field .Name of type int64, *json.UnmarshalTypeError
invalid character -> invalid character '\x1a' in string literal, *json.SyntaxError
unmarshal to nil -> json: Unmarshal(nil *main.Message), *json.InvalidUnmarshalError
  • Related