9

I have a redux file that contains my reducer and all of my actions via named exports.

export const reducer = (state, action) => ...

export myAction = action => {
    return {type: 'ACTION', action}
}
...

When in my test file I import the reducer and the actions. I have a renderWithRedux which takes in the reducer and creates a real store inside.

function renderWithRedux(ui, reducer = combineReducers(reducers), initialState = {}) {
    const store = createStore(reducer, initialState)
    const utils = render(<Provider store={store}>{ui}</Provider>)

    return {
        ...utils,
        store,
    }
}

The question I have is that the component I'm rendering is passed actions in the mapDispatchToProps in the connected component.

export default connect(mapStateToProps, { myAction })(MyComponent)

I want to mock the myAction in my particular use case this action would actually be a thunk and I want to see if the store updated.

The problem I have is how do I mock myAction but not the reducer. I've tried

jest.mock('./reducerFile', () => {
    return jest.fn().mockImplementation(() => {
        return {
            reducer: require.requireActual('./reducerFile').reducer,
            myAction: jest.fn()
        }
    })
})

But the reducer is still mocked somehow.

Is this even possible or am I just wanderlust.

Liam
  • 27,717
  • 28
  • 128
  • 190
JeffBaumgardt
  • 1,378
  • 3
  • 16
  • 24

3 Answers3

16

You can try this workaround:

jest.mock('./reducerFile', () => {
  const moduleMock = jest.requireActual(
    './reducerFile'
  );

  return {
    ...moduleMock,
    myAction: jest.fn(),
  };
});
Krzysztof Grzybek
  • 8,818
  • 2
  • 31
  • 35
  • something i noticed with this approach, the default export becomes an object with all the named exports, instead of just the default export... e.g if the name of the default export is Foo, after mocking, i have to access it as Foo.default, which causes some issues. is this intended? – brewster Oct 27 '20 at 05:38
  • This uses real implementation of all methods except one. OP asks to mock entire library but one. Your answer is the opposite of what OP asks. – schlingel Apr 16 '21 at 12:46
0

Unfortunately, you are out of luck. Jest mocks the entire module. It is not possible to partially mock a file. I personally would recommend splitting up the file to make testing easier for you.

See this discussion on github for an in-depth explanation as to why: https://github.com/facebook/jest/issues/936

tpdietz
  • 1,358
  • 9
  • 17
  • 1
    Not true, You can mock the entire lib then pass a factory which looks like this jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useRouteMatch: jest.fn().mockImplementation(() => ({ path: '/header' })), })); – Chris Marshall Jun 22 '21 at 15:57
0

You can do something like I did, in your test file:

const yourModule = require('../path/to/yourModule');

yourModule.myFn = jest.fn();

This would mock the named export function in your module.

Deepak
  • 2,487
  • 3
  • 21
  • 27