I want to verify that a mocked API is called with an object which does not contain a specific field.
expect(api.method).toBeCalledWith(expectedObject);
Since the actual parameters of the api.method
call can be a subset of the expectedObject
this test also passes if the actualObject
contains further fields (among which the specific field might be).
How can I rewrite the test in a way, that the tests fails if the actualObject
is not equal to the expectedObject
?
I want to verify that a mocked API is called with an object which does not contain a specific field.
expect(api.method).toBeCalledWith(expectedObject);
Since the actual parameters of the api.method
call can be a subset of the expectedObject
this test also passes if the actualObject
contains further fields (among which the specific field might be).
How can I rewrite the test in a way, that the tests fails if the actualObject
is not equal to the expectedObject
?
4 Answers
Reset to default 7you can try something like this
// get the first call to your method
const method = api.method.mock.calls[0];
//check if you have expectedObject as a subset of the arguments
expect(method[0]).toMatchObject(expectedObject);
//key is the field that shouldn't be part of the arguments
expect(method[0].has(key)).toEqual(false);
// since several tests use this mock I have to ensure to have the latest call
const lastMockApiCall = api.method.mock.calls[api.method.mock.calls.length - 1];
const apiCallParams = lastMockApiCall[0];
expect(apiCallParams).not.toHaveProperty('specificFieldIdontWant');
Even when the previous methods does work, it feels unfortable to access 0 indexes and nested properties and, in the end, doing manual parisons. So I prefer this method:
expect(api.method).toBeCalledWith(
expect.not.objectContaining({
notWantedProperty: expect.anything(),
})
);
Also, this will check for previous calls and not only the indexed call. And looks better on the logs:
Expected: ObjectNotContaining {"name": Anything}
Received: ...
Be careful, since it will try to match the whole object and not every property separately. For example, if your api has been called with the following object:
{
"foo": "foo",
"bar": "bar"
}
The following expect would NOT fail:
expect(api.method).toBeCalledWith(
expect.not.objectContaining({
foo: expect.anything(),
baz: expect.anything(),
})
);
Because you didn't call the API with both properties, so I would create a new expect for every property:
expect(api.method).toBeCalledWith(
expect.not.objectContaining({ foo: expect.anything() })
);
expect(api.method).toBeCalledWith(
expect.not.objectContaining({ baz: expect.anything() })
);
I'm using the following
expect(body[0].email).toEqual(undefined);
Which is passing when there is no email in the first object of the returned API array.