Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to unit test an innaccessible callback function that is called from a child React component using jest

I am unit testing a React 16 functional component that defines a callback and passes it as a property down to the next component to be invoked when a click event fires.

import React from 'react'

function OuterComponent() {

  const handleClick = useCallback(() => {
    openDialog() // <--- This code is inaccessible from my "OuterComponent.test.js" unit test 
  }

  return <MyDialog clickHandler={handleClick} />
}
export default OuterComponent

I am seeking 100% test coverage and would like to mock all other components/functions using jest that are not part of the "OuterComponent" component.

The problem I am having is that I can't seem to mock the MyDialog component in order to have it trigger the handleClick function.

I also tried to mock the component using this snippet but it still seems to try to load all the imports from MyDialog

jest.doMock('components/MyDialog', () => {
    return () => () => <div />
})
//... other mocks along with **openDialog**

//...and in my describe/it...
MyDialog.mockImplementation(() => {})

OuterComponent().handleClick()
expect(openDialog).toHaveBeenCalled()

The hope here was that I could render an empty div for MyDialog and just simply call the handleClick function to test it. Does anyone know what I could be doing wrong or have any other ideas of how to test it?

like image 505
Barry Avatar asked Dec 09 '25 08:12

Barry


1 Answers

I don't think you can mock a var in a closure. The best you can do is something along those lines:

import { fireEvent, render } from 'react-testing-library';

jest.mock(
  'components/MyDialog',
  () => ({ clickHandler }) => (
    <button
      onClick={clickHandler}
      test-id="button"
    >
      Click me
    </button>
  ),
);

it('should call clickHandler', () => {
  const onClick = jest.fn(() => null);
  const { queryByTestId } = render(<MyDialog clickHandler={onClick} />);
  fireEvent.click(queryByTestId('button'));
  expect(onClick.toHaveBeenCalledTimes(1));
});

You actually test the ability for you MyDialog to render something that can execute a callback.

like image 94
Nicolas SEPTIER Avatar answered Dec 10 '25 21:12

Nicolas SEPTIER