How to test if a mocked component receives the correct props in Jest and RTL (new since React 19)
This article serves 2 purposes. Firstly, explain how to test if a mocked component receives the correct props. Secondly, how this is different since React 19. tl;dr expect(User).toHaveBeenCalledWith( expect.objectContaining({ name: 'Peter', }), undefined // use undefined as second argument ); Setup Let's start with a simple example. We make a component that takes an array of names. This is the component: import { User } from './User'; export function Users({ users }) { return ( Users {users.map((user, i) => ( ))} ); } and this is the component: export function User({ name }) { return {name}; } Testing Our goal is to write a unit test for . We want to test in isolation. To do this, we need to mock . This is our initial test file: import { render, screen } from '@testing-library/react'; import { Users } from '../Users'; import { User } from '../User'; jest.mock('../User'); const users = ['Peter', 'John']; describe('', () => { // passes test('It renders', () => { render(); const heading = screen.getByRole('heading', { level: 1 }); expect(heading).toBeInTheDocument(); expect(heading).toHaveTextContent(/Users/); expect(User).toHaveBeenCalledTimes(2); }); }); We setup : render(); and test if Users is present. We already did an automatic mock of and verified if got called twice: expect(User).toHaveBeenCalledTimes(2);. This all works and passes. testing props Now, we want to check if was called with the correct props. We expect to have been called twice. (we already verified this). We expect to have been called the first time with prop "Peter": and the second time with prop "John": . But, how do we do this? Here is a new test: test('It calls with the correct props', () => { render(); expect(User).toHaveBeenCalledTimes(2); // fails expect(User).toHaveBeenNthCalledWith(1, { name: 'Peter', }); }); We expect the mock to have been called the first name (nth is 1) with an object: { name: 'Peter' }. At first glance this seems like it should work. But it doesn't. Here is the error message: *edited n: 1 Expected: {"name": "Peter"} Received {"name": "Peter"}, + undefined, What this tells us is that there is a second argument: + undefined that is missing, undefined. Before explaining, let's add that: // passes expect(User).toHaveBeenNthCalledWith( 1, { name: 'Peter', }, undefined ); And it works. But, what is undefined? What is this second argument? To be honest, I'm not quite sure. On top of that, before React 19, the second argument wasn't undefined but it was an empty object: {}. new in React 19 Before React 19, I would've written the above test differently: // passes before react 19 // fails in react 19 expect(User).toHaveBeenNthCalledWith( 1, { name: 'Peter', }, {} ); or with some more flexibility: // passes before react 19 // fails in react 19 expect(User).toHaveBeenNthCalledWith( 1, { name: 'Peter', }, expect.anything() ); expect.anything() matches with everything except null or undefined. But what is this second argument? It seems to be some legacy argument that refers to context. But React has long since reworked context and doesn't use the second argument anymore ... but still expects something there. Before React 19, it expected {}. With React 19 the React team reworked this and the second argument now needs to be undefined. And that is all I know about it. A last improvement This is our test in React 19: // passes expect(User).toHaveBeenNthCalledWith( 1, { name: 'Peter', }, undefined ); We explicitly use undefined because expect.anything() does not match undefined. There is one more improvement to be made. In our case we only have one prop for , name. But suppose there are different props and we don't need them all then this pattern would fail. Therefore, it's good practice to use expect.objectContaining: expect(User).toHaveBeenNthCalledWith( 1, expect.objectContaining({ name: 'Peter', }), undefined ); This will pass, even if there are other properties. Conclusion And that is all. A quick explanation of how to test if a mocked component got called with the correct props, followed by a vague explaination about a second argument that was reworked in React 19. For closure, here is the full test file: import { render, screen } from '@testing-library/react'; import { Users } from '../Users'; import { User } from '../User'; jest.mock('../User'); const users = ['Peter', 'John']; describe('', () => { test('It renders', () => { render(); const heading = screen.getByRole('heading', { level: 1 }); expect(heading).toBeInTheDocument(); expect(heading).toHaveTextContent(/Users/); expect(User).toHa

This article serves 2 purposes. Firstly, explain how to test if a mocked component receives the correct props. Secondly, how this is different since React
19.
tl;dr
expect(User).toHaveBeenCalledWith(
expect.objectContaining({
name: 'Peter',
}),
undefined // use undefined as second argument
);
Setup
Let's start with a simple example. We make a
component that takes an array of names.
<Users users={['Peter', 'John']} />
This is the
component:
import { User } from './User';
export function Users({ users }) {
return (
<>
<h1>Usersh1>
<ul>
{users.map((user, i) => (
<User key={i} name={user} />
))}
ul>
>
);
}
and this is the
component:
export function User({ name }) {
return <li>{name}li>;
}
Testing
Our goal is to write a unit test for
. We want to test
in isolation. To do this, we need to mock
. This is our initial test file:
import { render, screen } from '@testing-library/react';
import { Users } from '../Users';
import { User } from '../User';
jest.mock('../User');
const users = ['Peter', 'John'];
describe(' ', () => {
// passes
test('It renders', () => {
render(<Users users={users} />);
const heading = screen.getByRole('heading', { level: 1 });
expect(heading).toBeInTheDocument();
expect(heading).toHaveTextContent(/Users/);
expect(User).toHaveBeenCalledTimes(2);
});
});
We setup
: render(
and test if
is present. We already did an automatic mock of Users
and verified if got called twice: expect(User).toHaveBeenCalledTimes(2);
. This all works and passes.
testing props
Now, we want to check if
was called with the correct props. We expect
to have been called twice. (we already verified this). We expect
to have been called the first time with prop "Peter":
and the second time with prop "John":
. But, how do we do this? Here is a new test:
test('It calls with the correct props', () => {
render(<Users users={users} />);
expect(User).toHaveBeenCalledTimes(2);
// fails
expect(User).toHaveBeenNthCalledWith(1, {
name: 'Peter',
});
});
We expect the
mock to have been called the first name (nth is 1) with an object: { name: 'Peter' }
. At first glance this seems like it should work. But it doesn't. Here is the error message:
*edited
n: 1
Expected: {"name": "Peter"}
Received
{"name": "Peter"},
+ undefined,
What this tells us is that there is a second argument: + undefined
that is missing, undefined
. Before explaining, let's add that:
// passes
expect(User).toHaveBeenNthCalledWith(
1,
{
name: 'Peter',
},
undefined
);
And it works. But, what is undefined
? What is this second argument? To be honest, I'm not quite sure. On top of that, before React 19
, the second argument wasn't undefined
but it was an empty object: {}
.
new in React 19
Before React 19
, I would've written the above test differently:
// passes before react 19
// fails in react 19
expect(User).toHaveBeenNthCalledWith(
1,
{
name: 'Peter',
},
{}
);
or with some more flexibility:
// passes before react 19
// fails in react 19
expect(User).toHaveBeenNthCalledWith(
1,
{
name: 'Peter',
},
expect.anything()
);
expect.anything()
matches with everything except null
or undefined
.
But what is this second argument? It seems to be some legacy argument that refers to context. But React
has long since reworked context and doesn't use the second argument anymore ... but still expects something there. Before React 19
, it expected {}
.
With React 19
the React
team reworked this and the second argument now needs to be undefined
. And that is all I know about it.
A last improvement
This is our test in React 19
:
// passes
expect(User).toHaveBeenNthCalledWith(
1,
{
name: 'Peter',
},
undefined
);
We explicitly use undefined
because expect.anything()
does not match undefined
.
There is one more improvement to be made. In our case we only have one prop for
, name. But suppose there are different props and we don't need them all then this pattern would fail. Therefore, it's good practice to use expect.objectContaining
:
expect(User).toHaveBeenNthCalledWith(
1,
expect.objectContaining({
name: 'Peter',
}),
undefined
);
This will pass, even if there are other properties.
Conclusion
And that is all. A quick explanation of how to test if a mocked component got called with the correct props, followed by a vague explaination about a second argument that was reworked in React 19
. For closure, here is the full test file:
import { render, screen } from '@testing-library/react';
import { Users } from '../Users';
import { User } from '../User';
jest.mock('../User');
const users = ['Peter', 'John'];
describe(' ', () => {
test('It renders', () => {
render(<Users users={users} />);
const heading = screen.getByRole('heading', { level: 1 });
expect(heading).toBeInTheDocument();
expect(heading).toHaveTextContent(/Users/);
expect(User).toHaveBeenCalledTimes(2);
});
test('It calls with the correct props', () => {
render(<Users users={users} />);
expect(User).toHaveBeenCalledTimes(2);
// fails
/*expect(User).toHaveBeenNthCalledWith(
1,
expect.objectContaining({
name: 'Peter',
}),
);*/
//fails
/*expect(User).toHaveBeenNthCalledWith(
1,
expect.objectContaining({
name: 'Peter',
}),
expect.anything()
);*/
// works
expect(User).toHaveBeenNthCalledWith(
1,
expect.objectContaining({
name: 'Peter',
}),
undefined
);
expect(User).toHaveBeenNthCalledWith(
2,
expect.objectContaining({
name: 'John',
}),
undefined
);
});
});