Home > Enterprise >  Test the function inside click handler - Jest, React testing Library
Test the function inside click handler - Jest, React testing Library

Time:07-30

I have a button click handler in which I call another function. I need to test the function call inside of the handler:

SomeComponent

...
const handler = () => {
  someFunction();
}
...
<button data-testId="button" onClick={handler}>Click Me</button>

test

describe('Button click', () => {
  it('button click', async () => {
    render(<SomeComponent />);

    const button = await screen.findByTestId('button');
    fireEvent.click(button);
    // some silly test case just for example
    expect(button).toBeInTheDocument();
  });
});

While doing this, it covers the handler but not the inner function itself:

const handler = () => { <<<<<<< covered
  someFunction();       <<<<<<< UNCOVERED
}.                      <<<<<<< covered

The main question here is how can I test the inner function call? If I need to mock it, how should I do it, because the mocked function will not test the actual one?

UPDATE

Also, my someFunction doesn't change anything in the scope of this component, so I can't catch it by comparing the inner state or document change.

SomeFunction is coming from another file and I tested it separately.

CodePudding user response:

It depends on where someFunction is defined. If it's a property given to <SomeComponent /> then you could do something like this:

describe('Button click', () => {
  it('button click', async () => {
    const someFunction = jest.fn();
    render(<SomeComponent someFunction={someFunction} />);

    const button = await screen.findByTestId('button');
    fireEvent.click(button);

    // if there are some precise arguments given to `someFunction` maybe 
    // use `toHaveBeenCalledWith` instead
    expect(someFunction).toHaveBeenCalled();
  });
});

But if it's defined in a separate hook then you should mock this hook. For instance here let's assume there a useSomeFunction that directly returns this someFunction:

import { useSomeFunction  } from '../path/to/useSomeFunction';

jest.mock('../path/to/useSomeFunction', () => ({
  useSomeFunction: jest.fn(),
}));

describe('Button click', () => {
  it('button click', async () => {
    const mockSomeFunction = jest.fn();
    useSomeFunction.mockImplementation(() => mockSomeFunction);
    render(<SomeComponent />);

    const button = await screen.findByTestId('button');
    fireEvent.click(button);
    // if there are some precise arguments given to `someFunction` maybe 
    // use `toHaveBeenCalledWith` instead
    expect(mockSomeFunction).toHaveBeenCalled();
  });
});

And if it's simply a function defined elsewhere you could adapt the example I gave with hook mocking:

import { someFunction } from '../path/to/util';

jest.mock('../path/to/util', () => ({
  someFunction: jest.fn(),
}));

describe('Button click', () => {
  it('button click', async () => {

    render(<SomeComponent />);

    const button = await screen.findByTestId('button');
    fireEvent.click(button);

    // if there are some precise arguments given to `someFunction` maybe 
    // use `toHaveBeenCalledWith` instead
    expect(someFunction).toHaveBeenCalled();
  });
});

CodePudding user response:

someFunction() needs to generate some side effects to your app. You can test those side effects. For instance if someFunction() was incrementing a count state value you could test for that in your component to check if count was incremented when button was clicked.

  • Related