5

I'm writing unit tests for an API.

If I do something like this :

const apiResponse:object = JSON.parse(body)
expect(apiResponse).toHaveProperty('error')

and the API is not returning JSON, then I get something like :

SyntaxError: Unexpected token p in JSON at position 0 at JSON.parse ()

Rather than getting an error in my tests, I'd like my test to fail.

What is a jest test I can do that says;
is this string I've received parsable as valid JSON?

skyboyer
  • 22,209
  • 7
  • 57
  • 64
Kris Randall
  • 686
  • 1
  • 7
  • 12
  • 2
    Wrap it in a try/catch. There's no built in way of testing for json validity other than parsing it. – Adrian Mar 27 '18 at 09:01
  • Expanding on @Adriani6 Change your code to wrap the parse in a Try/Catch, then return an exception when the parse fails, and then Jest can test for the exception with bad JSON, and another normal test for good JSON data. – Steven Scott Mar 27 '18 at 14:21

2 Answers2

9

I solved this by adding a helper function I found here

const isJSON = (str:string) => {
    try {
        const json = JSON.parse(str);
        if (Object.prototype.toString.call(json).slice(8,-1) !== 'Object') {
        return false
        }
    } catch (e) {
        return false
    }
    return true
}

and then am able to do this :

expect(isJSON(body)).toBe(true)
Kris Randall
  • 686
  • 1
  • 7
  • 12
6

You can simply use Jest's .not.toThrow() to assert that the JSON parsing doesn't throw an error.

Here is an example I made that asserts an object can be parsed to valid JSON:

it("Produces metadata object that can be parsed to valid JSON", () => {
    const meta = articleMetaData(article);

    const parseJson = () => {
        const json = JSON.stringify(meta);
        JSON.parse(json);
    };

    expect(parseJson).not.toThrow();
});

If, for example, the object had a circular structure:

var obj = {
  a: "foo",
  b: obj
}

The test would fail:

Expected the function not to throw an error.
Instead, it threw:
    TypeError: Converting circular structure to JSON
Nigel Gilbert
  • 439
  • 5
  • 5