213

How can I get the arguments called in jest mock function?

I want to inspect the object that is passed as argument.

NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
Bruno Quaresma
  • 9,457
  • 7
  • 32
  • 50

7 Answers7

326

Just use mockObject.calls. In my case I used:

const call = mockUpload.mock.calls[0][0]

Here's the documentation about the mock property

jmrah
  • 5,715
  • 3
  • 30
  • 37
Bruno Quaresma
  • 9,457
  • 7
  • 32
  • 50
  • Other than mock function, is there any other way to get the arguments of the function in jest? – Coder Aug 27 '18 at 11:55
  • 10
    Thank you! To others and my future self: If you get a compilation error `Tuple type '[]' of length '0' has no element at index '0'.` on the second `0`, you can get around it by using `const call = (mockUpload.mock.calls[0] as any[])[0];`. – Cameron Hudson Dec 13 '19 at 23:59
  • Somehow Jest tries to refine the types when you pass an implementation like `jest.fn(() => "foobar")`, but not when you just use `jest.fn()`, in this case `calls` is of type any (instead of being an array potentially empty). – Eric Burel Jun 14 '21 at 13:08
  • 4
    Digged the types a bit more: the right way in TypeScript is `jest.fn((args) => "foobar")`: explicitely defining `args` will results in a better typings, and `mock.calls[0][0]` will be accepted by TypeScript. This is because if you use 2 args in your mock, `mock.calls[0]` is an array of length 2. If you use 1 arg, length 1, and 0 args => length 0. So in your mock just use the same number of arguments as your function is expecting, even if you don't use them. – Eric Burel Jun 14 '21 at 13:12
  • 1
    Regarding the `Tuple type '[]' of length '0' has no element at index '0'.` error: in my case, I had typed my mock using `SpyInstance` without understanding the two generic parameters for that type. `SpyInstance` takes the return type `R` and an array of argument types `A`. Specifying a type of `SpyInstance` allowed me to get any number of arguments from the calls of my mock without any errors. – JoshuaCWebDeveloper Nov 13 '21 at 04:46
  • const call = mockUpload.mock.calls.flat(DEPTH); will give you one dimension array ```DEPTH``` is a number. Doc: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat – Clister Dmello Jan 04 '22 at 12:59
84

Here is a simple way to assert the parameter passed.

expect(mockedFunction).toHaveBeenCalledWith("param1","param2");
Kitson
  • 1,153
  • 9
  • 22
Senthil Arumugam SP
  • 1,461
  • 12
  • 17
21

You can use toHaveBeenCalledWith() together with expect.stringContaining or expect.arrayContaining() or expect.objectContaining()

...
const { host } = new URL(url);
expect(mockedFunction).toHaveBeenCalledWith("param1", expect.stringContaining(`http://${host}...`);
jflaga
  • 4,610
  • 2
  • 24
  • 20
  • 1
    Thank you so much! This combination was exactly what I was looking for. Also, if you do not care about the first or second parameter, you can use `expect.anything()` on it. – soutoner Jan 13 '22 at 11:57
3

I prefer lastCalledWith() over toHaveBeenCalledWith(). They are both the same but the former is shorter and help me reduce the cognitive load when reading code.

expect(mockedFn).lastCalledWith('arg1', 'arg2')
NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
  • 10
    This does not answer the question. He is not asking how to CHECK what argument it was called with, but rather GET that argument so he can inspect it. – Javi Marzán Oct 20 '20 at 12:46
  • 4
    @JaviMarzán I came from google because I wanted to know how to assert the function arguments. People who come to this question may not necessarily want to inspect the arguments, but to get the argument and assert it. That's why I leave the answer here in the hope of helping others who have similar problem. – NearHuscarl Oct 20 '20 at 13:04
3

Use an argument captor, something like this:

let barArgCaptor;
const appendChildMock = jest
    .spyOn(foo, "bar")
    .mockImplementation(
    (arg) => (barArgCaptor = arg)
    );

Then you could expect on the captor's properties to your heart's content:

expect(barArgCaptor.property1).toEqual("Fool of a Took!");
expect(barArgCaptor.property2).toEqual(true);
Saulo Silva
  • 1,219
  • 1
  • 20
  • 37
3

I find I often want to validate the exact arguments of exact calls to my mock functions; my approach is:

let mockFn = jest.fn((/* ... */) => { /* ... */ });

// ... do some testing which triggers `mockFn` ...

expect(mockFn.mock.calls).toEqual([

  // Ensure `mockFn` was called exactly 3 times:
  
  // The 1st time with arguments "a" and 1,
  [ 'a', 1 ],

  // 2nd time with arguments "b" and 2,
  [ 'b', 2 ],
  
  // 3rd time with arguments "c" and 3
  [ 'c', 3 ]

]);

Gershom Maes
  • 7,358
  • 2
  • 35
  • 55
1

we can add a mockImplementation to the mock method and have it return the arguments back which can be used to evaluate.

Amir Ram
  • 11
  • 1
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – jasie Aug 16 '22 at 12:30