Evanss
Evanss

Reputation: 23593

Mock a dependancy within a dependancy with Jest?

I need to test this function:

import dependency from 'dependency';

export default values => (dispatch) => {
  dispatch(dependency(values));
  // More code
};

Ive got a test which asserts that dispatch called dependency:

import functionToTest from 'function-to-test';

jest.mock('dependency', () => () => 'dependency res');

describe('functionToTest', () => {
    const dispatch = jest.fn();
    functionToTest({ foo: 'bar' })(dispatch);

    test('test', () => {
        expect(dispatch.mock.calls[0][0]).toBe('dependency res');
    });
});

I need to assert that dependancy was called with { foo: 'bar' }. I tried naming my dependancy mock but when I console.log it it's undefined:

import functionToTest from 'function-to-test';

const dependencyMock = jest.mock('dependency', () => () => 'dependency res');

describe('functionToTest', () => {
    const dispatch = jest.fn();
    functionToTest({ foo: 'bar' })(dispatch);

    test('test', () => {
        expect(dispatch.mock.calls[0][0]).toBe('dependency res');

        console.log(dependencyMock.mock.calls) // undefined
    });
});

I attempted to create a new jest function spy hoping that I could inspect it's arguments, but this returned an error

import functionToTest from 'function-to-test';

const spy = jest.fn(() => 'save-form-data');

const dependencyMock = jest.mock('dependency', () => spy);

describe('functionToTest', () => {
    const dispatch = jest.fn();
    functionToTest({ foo: 'bar' })(dispatch);

    test('test', () => {
        expect(dispatch.mock.calls[0][0]).toBe('dependency res');

        console.log(dependencyMock.mock.calls) // undefined
    });
});

The module factory of jest.mock() is not allowed to reference any out-of-scope variables.

Upvotes: 2

Views: 1311

Answers (1)

Brian Adams
Brian Adams

Reputation: 45810

You're close!

You need to move the mock function inside the module factory function passed to jest.mock.

Then you just need to import dependency into the test and check that it was called as expected:

import functionToTest from 'function-to-test';
import dependency from 'dependency';  // <= dependency will be...

jest.mock('dependency', () =>
  jest.fn(() => 'dependency res')  // <= ...this mock function
);

describe('functionToTest', () => {
  it('should dispatch dependency', () => {
    const dispatch = jest.fn();
    functionToTest({ foo: 'bar' })(dispatch);

    expect(dispatch.mock.calls[0][0]).toBe('dependency res');  // Success!
    expect(dependency).toHaveBeenCalledWith({ foo: 'bar' });  // Success!
  });
});

Note that by default babel-jest hoists jest.mock calls and they run before anything else in the test file, so module factory functions passed to jest.mock have to be completely self-contained.

Upvotes: 2

Related Questions