Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Jest matchers to work with JSON strings

License

NotificationsYou must be signed in to change notification settings

duailibe/jest-json

Repository files navigation

npmCIcodecov

Jest matchers to work with JSON strings.

Setup

Note: If you're using Jest < 27.2.5, you should stick tojest-json@^1.0.

Addjest-json to your Jest config:

{"setupTestFrameworkScriptFile":"jest-json"}

Or if you're already using another test framework, create a setup file and require each of them:

require("jest-json");// require("some-jest-library);

Motivation

Say you have a functionfetchData the callsfetch with a JSON body and you want to assert thatfetchData is building the JSON string correctly.

See thisrepl.it for a working example of this problem.

functionfetchData(userId,fields=[]){if(!fields.includes("profilePicture")){fields=fields.concat(["profilePicture"]);}returnfetch("/users",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({params:{id:userId},      fields,}),});}

One option to write the test would be to check the final string:

test("fetchData",()=>{fetchData("ab394js",["name","website"]);expect(fetch).toHaveBeenCalledWith("/users",{method:"POST",headers:expect.anything(),body:JSON.stringify({params:{id:"ab394js"},fields:["name","website","profilePicture"],}),});});

Ok, this works, but that has a few problems:

  • you are testing that"profilePicture" will be added to the end of thefields list,
  • you are testing the exact orders the keys of the body JSON are added.

If someone changes the test to insert"profilePicture" in the beginning of the list, or change the JSON toJSON.stringify({ fields, params }), your test will now fail because the JSON string changed, even though it's equivalent to the one in the test. That means we have a flaky test. One way to fix it would be:

global.fetch=jest.fn();test("fetchData",()=>{fetchData("ab394js",["name","website"]);expect(fetch).toHaveBeenCalledWith("/users",{method:"POST",headers:expect.anything(),body:expect.anything(),});expect(JSON.parse(fetch.mock.calls[0][1].body)).toEqual({params:{id:"ab394js"},fields:expect.arrayContaining(["name","website","profilePicture"]),});});

That's better, and now we can even useexpect.arrayContaining() to make sure we assert that the values are present, but don't care about the order.

But that's a really inconvenient way to get the string we're interested (fetch.mock.calls[0][1].body).

Now compare that test to this:

global.fetch=jest.fn();test("fetchData",()=>{fetchData("ab394js",["name","website"]);expect(fetch).toHaveBeenCalledWith("/users",{method:"POST",headers:expect.anything(),body:expect.jsonMatching({params:{id:"ab394js"},fields:expect.arrayContaining(["name","website","profilePicture"]),}),});});

Now that's a very neat test.

API

expect.jsonMatching

In the example above, you can use theexpect.jsonMatching asymmetric matcher:

expect(foo).toHaveBeenCalledWith("url",expect.jsonMatching({foo:"bar",spam:"eggs",}));

You can include other asymmetric matchers inside like:

expect.jsonMatching(expect.objectContaining({foo:expect.stringMatching("bar")}))

expect().toMatchJSON()

It's just sugar for callingJSON.parse() and thenexpect().toEqual():

expect(json).toMatchJSON(expected);// equivalent to:consttmp=JSON.parse(json);expect(tmp).toEqual(expected);

License

MIT


[8]ページ先頭

©2009-2025 Movatter.jp