Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest how to wait for mock to be called based on simulate event

I have a test like this which fails because mock is not called, the problem is that the mock is called but before test finished.

test('should submit if proper values', () => {
  const spy = jest.fn().mockReturnValue({
    data: {
      authenticateUser: {
        id: 123,
        token: 'lol'
      }
    }
  });
  mountedWrapper.setProps({
    loginMutation: spy
  });
  expect(spy).not.toHaveBeenCalled();
  email.simulate('change', {
    target: { name: 'username', value: '[email protected]' }
  });
  password.simulate('change', {
    target: { name: 'password', value: 'secret' }
  });
  form.simulate('submit');
  expect(spy).toHaveBeenCalled();
});

However I can get the test to pass if I add the following setTimeout

  setTimeout(() => {
    expect(spy).toHaveBeenCalled();
  }, 0);

However I am looking for a nicer approach to the above problem. Any solutions out there without setTimeout ?

like image 566
StevieB Avatar asked Sep 05 '25 03:09

StevieB


1 Answers

It looks like you're trying to test some asynchronous code. Did you read this? Under callbacks section you can find:

By default, Jest tests complete once they reach the end of their execution. That means this test will not work as intended:

// Don't do this!
test('the data is peanut butter', () => {
  function callback(data) {
    expect(data).toBe('peanut butter');
  }

  fetchData(callback);
});

The problem is that the test will complete as soon as fetchData completes, before ever calling the callback. There is an alternate form of test that fixes this. Instead of putting the test in a function with an empty argument, use a single argument called done. Jest will wait until the done callback is called before finishing the test.

test('the data is peanut butter', done => {
  function callback(data) {
    expect(data).toBe('peanut butter');
    done();
  }

  fetchData(callback);
});

If done() is never called, the test will fail, which is what you want to happen.

That's example for callback, but you can also use promises, .resolves/.rejects, and async/await.

like image 89
robi24 Avatar answered Sep 07 '25 23:09

robi24