Search code examples
unit-testingreactjsreactjs-fluxjestjs

Mock Action functions in Jest test


How would one go about calling a function from an imported action module? Here is my component

class Task extends Component {
 handleClick(e) {
  e.preventDefault();
  Actions.returnTask(this.props.id);
 }
 render() {...}
}

and tests that look like this:

jest.dontMock('./Task');
jest.dontMock('./Actions');

describe('Tasks', function() {
 let renderedComponent;
 let mockReturnTask;
 let TaskActions;
 beforeEach(function() {
  renderedComponent = TestUtils.renderIntoDocument(
   <Task task={testTask} key={1} />
    );
   Actions = require('./Actions');
   mockReturnTask = jest.genMockFn();
   Actions.returnTask = mockReturnTask;
  });
  it('should call a returnTask action on Actions', function() {
   renderedComponent.handleClick(event);
   expect(mockReturnTask).toBeCalled();
  });
});

When running my test it tells me that the function was not called. If I do expect(Actions.returnTask).toBeCalled(); I get an error message that toBeCalledWith() should be used on a mock function error. How do I mock a function on the external Actions and check that it is called in my tests? I feel like my method above should be working.


Solution

  • Your example doesn't include the require of Task but I'm pretty sure of what happened here. Jest users must be aware of what require they do, and when.

    Chronologically:

    1. jest is set to never mock Actions and Task
    2. Task component is required, jest requires it for real
    3. Actions is required because it is required in the Task component. jest requires it for real.
    4. Task component is instantiated
    5. Actions.returnTask is monkey-patched but it's not the function the component is bind with, it's a new function who exist only in the test.

    To make your component using a jest mocked function, you have to require and monkey-patch Actions before requiring Tasks

    Be aware that you don't have to unmocked Actions if you mock a function of Actions right after. It's exactly what the jest auto-mocking killing feature is made for : remove jest.dontMock('./Actions'); and all references to your Actions module. The test should be working.