Gabriel P.
Gabriel P.

Reputation: 3560

Mock function is not called in click event while testing with jest and enzyme

I am trying to test a redux connected react component, namely Cart, and I cannot get the below test to work. I want to see if an action is called inside a click handler for a button (imported from the material-ui package).

The action is mapped to props via mapDispatchToProps.

const mapDispatchToProps = dispatch =>
  bindActionCreators(SelectItemGalleryActions, dispatch);

I am also using

import configureStore from 'redux-mock-store';

to pass the mock store to my component in test.

The handler is called but the spy is not recording that it has been called. I have tried most solutions I have found here or on github (shallow, simulate, dives, using jest.fn() instead of spy() ...); do you have any ideas? I am assuming that a different reference to the mock function I am trying to test is called.

First I am passing a mock store and an action

const props = {
  store: mockStore({ selectItemGallery: { cartItems: [{ name: 'one' }] } }),
  removeAllItemsFromCartAction: spy()
};
const wrapper = mount(<Cart {...props} />);

After that I search for my button and simulate clicks on it

const button = wrapper.find(Button).at(0);
button.prop('onClick')('test1');
button.prop('onClick')('test2');

The clicks work when I run the test. I get console.log() outputs from inside the handler.

Expectations

expect(props.removeAllItemsFromCartAction.called).toBe(true);

However it is not called.

Here is the actual handler

 <Button
    color="primary"
    onClick={x => {
      console.log(`onClick called on component with info ${x}`);
      removeAllItemsFromCartAction();
      console.log('removeAllItemsFromCartAction call is above me');
    }}>    
        {t('Clear All')}
 </Button>

The console displays

console output for test

Any hints or ideas are welcome. Thanks.

Versions:

"enzyme": "^3.8.0",
"enzyme-adapter-react-16": "^1.7.1",
"jest": "^23.6.0",
"sinon": "^7.2.2",
"react": "^16.8.2"

Upvotes: 0

Views: 5854

Answers (2)

Gabriel P.
Gabriel P.

Reputation: 3560

This seems to be not the correct way to test if an action mapped to props via mapDispatchToProps was called.

The dispatch from the mock store is actually called and we just need to verify if it sends the correct action (https://redux.js.org/recipes/writing-tests).

The correct test would be:

  it('Should call the removeAllItemsFromCartAction', () => {
    const props = {
      store: mockStore({ selectItemGallery: { cartItems: [{ name: 'one' }] } })
    };
    const wrapper = mount(<Cart {...props} />);
    const button = wrapper.find(Button).at(0);
    button.prop('onClick')();
    console.log(props.store.getActions());
    expect(props.store.getActions()).toEqual([
      { type: 'REMOVE_ALL_ITEMS_FROM_CART' }
    ]);
  });

Upvotes: 1

Chase
Chase

Reputation: 2304

These tests can be really finicky, but I suspect the issue is how you setup your spy since according to your console logs the function is getting hit. First, I don't think you actually need a spy and you could just use a mock function that is passed in as long as removeAllItemsFromCartAction() is actually on your component props.

const myMock = jest.fn();
const props = {
  store: mockStore({ selectItemGallery: { cartItems: [{ name: 'one' }] } }),
  removeAllItemsFromCartAction: myMock
};
const wrapper = mount(<Cart {...props} />);
const button = wrapper.find(Button).at(0);
button.simulate("click");
expect(myMock).toHaveBeenCalled();

You probably have already tried this, but it is my only idea here.

Upvotes: 0

Related Questions