Search code examples
reactjstypescriptjestjsreselect

Using jest.mocked to mock a selector factory


We have a selector factory like this:

const selectItems = state => state.items
const selectCategory = state => state.category
 
const makeSelectItemsByCategory = () => {
    const selectItemsByCategory = createSelector(
        [selectItems, selectCategory],
        (items, category) => items.filter(item => item.category === category)
    )
    return selectItemsByCategory
}

It is being used in a file that I am trying to test.

...
const itemsByCategory = makeSelectItemsByCategory()(getState())
// do stuff with this...

Now, in my test file, I am trying to mock the makeSelectItemsByCategory function and have typically done something like:

jest.mock('/path/to/selector/file', () => ({
    makeSelectItemsByCategory: jest.fn()
}))

describe('my-file-name', () => {
    beforeEach(() => { jest.resetAllMocks() })

    it('does stuff', () => {
         jest.mocked(makeSelectItemsByCategory).mockReturnValueOnce(() => []) // error here
         ....
    })
})

In other words, I want to mock that the return value of the makeSelectItemsByCategory is a function that returns an empty list.

However, I get a red squiggly line error on the argument to mockReturnValueOnce:

Argument of type '() => never[]' is not assignable to parameter of type '((state: TReduxState) => any[]) & OutputSelectorFields<(args_0: TMyType[]) => any[], { clearCache: () => void; }> & { ...; }'. Type '() => never[]' is not assignable to type 'OutputSelectorFields<(args_0: TMyType[]) => any[], { clearCache: () => void; }>'.ts(2345)

Any help would be greatly appreciated.


Solution

  • Mock the selector is not recommended, you should create a mock store with different state and use the real selector implementation to calculate the derived data.

    You can create a mock selector using createSelector and let the output selector returns an array.

    import { createSelector } from 'reselect';
    import { makeSelectItemsByCategory } from './selector';
    
    jest.mock('./selector', () => ({
      makeSelectItemsByCategory: jest.fn(),
    }));
    
    describe('my-file-name', () => {
      beforeEach(() => {
        jest.resetAllMocks();
      });
    
      it('does stuff', () => {
        const selectItemsByCategoryMock = createSelector(
          () => undefined,
          () => [1, 2, 3],
        );
        jest.mocked(makeSelectItemsByCategory).mockReturnValueOnce(selectItemsByCategoryMock);
    
        const itemsByCategory = makeSelectItemsByCategory()({});
        expect(itemsByCategory).toEqual([1, 2, 3]);
      });
    });