Search code examples
javascriptreactjsjestjsreact-test-renderer

Jestjs how to test function being called inside another function


For testing I use jest and react-test-renderer. It should be simple to test, however I have a hard time finding the proper example. I have tried to do something like that (in general I keep the functions in separate files):

utils.js

export const childFunction = () => 'something';    
const parentFunction = () => childFunction();
export default parentFunction;

utils.test.js

import parentFunction from './utils.js';


it('childFunction should be called', () => {
 const childFunction = jest.fn();
 parentFunction();
 expect(childFunction).toBeCalled();
})

The fragment const childFunction = jest.fn(); definitely won't work. While calling, parentFunction's body cares only about its own scope. But it also won't work if I import childFunction and do jest.mock(childFunction), because jest.mock needs a string, a url to a module, and not the function itself.

The example above doesn't work and I'm searching for an alternative. However this works after rendering the component with ShallowRenderer. And I'd like to achieve a similar behaviour with a function nested inside another function.

class Component extends React.Component {
 componentDidMount() {parentFunction()}
 render() {...}
}

const renderer = new ShallowRenderer();
describe("testing parentFunction", () => {
  renderer.render(<Component/>);
  it("parentFunction should be called", () => {
    expect(parentFunction).toBeCalled();
  });
});

Solution

  • There's no way to spy on function call if a function isn't called as object method.

    As explained in this answer, due to how ES modules work, it's possible to spy or mock a function only if it was exported from a module and is used in another module. This way it can be spied on module * object, or be mocked with jest.mock.

    If this isn't the case, it should be tested indirectly:

    expect(childFunction()).toBe('something');
    expect(parentFunction()).toBe('something');