Why Jest's toStrictEqual
Fails to Match JSON Responses from fetch
Testing your application's interactions with external APIs is crucial. Jest's toStrictEqual
matcher is often the go-to for verifying data equality, but a common pitfall arises when comparing JSON responses from the fetch
API.
Let's illustrate this problem with a simple example.
Scenario:
You have a function that retrieves data from an API using fetch
and expects a JSON response:
async function fetchData() {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
}
Now, you want to write a Jest test to ensure the function returns the expected JSON data:
test('fetches data successfully', async () => {
const expectedData = {
name: 'John Doe',
age: 30,
};
const data = await fetchData();
expect(data).toStrictEqual(expectedData);
});
You might find that this test fails despite data
seeming to hold the correct data.
The Issue:
The problem stems from the fact that fetch
returns a Response
object, and response.json()
returns a Promise that resolves to the parsed JSON object. While your test is expecting an object, what it actually receives is a Promise that will eventually resolve to the object. This leads to the comparison between the Promise and the expected object, which always fails because they are not strictly equal.
Solution:
The key to resolving this is to await the response.json()
Promise before comparing the data:
test('fetches data successfully', async () => {
const expectedData = {
name: 'John Doe',
age: 30,
};
const data = await fetchData();
expect(data).toStrictEqual(expectedData);
});
Explanation:
By adding await
before response.json()
, we are explicitly waiting for the Promise to resolve and retrieve the actual JSON object before making the comparison. This allows toStrictEqual
to perform the deep equality check correctly, ensuring that the received data matches the expected structure.
Additional Notes:
-
For situations where you want to test the entire
Response
object (status code, headers, etc.), you can directly compare theResponse
object itself instead of just the parsed JSON data. -
While
toStrictEqual
offers a deep comparison, remember that you can also use other Jest matchers liketoEqual
ortoMatchObject
depending on your specific needs and the level of detail required in your test.
Key Takeaway:
Always ensure that your test is comparing the actual value you are expecting, not a Promise that resolves to that value. By understanding the nuances of fetch
and response.json()
, you can write accurate and reliable tests for your API interactions.