reactjstestingjestjsreact-testing-librarymobx-react

How to override mock of an object using jest? I am using `jest.mock()` to mock the object and would like to override the mock for each test case


I'm trying to mock an object to test some implementation using jest which can be overridden for each testcase. Please let me know if you have solved similar problem or any other better solution to mock an object using jest.

import {obj} from "./filepath/obj";

jest.mock("./filepath/obj", () => ({
  obj:{
    search: jest.fn(),
    items:[1,2,3]
  }

}))

test("test 1", () => {
  expect(obj.items.length).toBe(3); // works
})

// now if I try to override, for some other test case that doesn't work
test("test 1", () => {
  jest.mock("./filepath/obj", () => ({
    obj:{
      search: jest.fn(),
      items:[]
    }

  }))
   
  expect(obj.items.length).toBe(0); // doesn't work
})

How can we override the mock implementation for an object which can work in each test case?

more context: the object is a mobx store object exported from the file where we have the store definition. Then, we're using that store object in a component by importing it. Now, while testing the component, we're trying to mock the store object as mentioned above.


Solution

  • There is no need to pass the factory parameter to jest.mock(), just let jest mock a module with an auto-mocked version when it is required.

    That means the obj.items will be replaced with empty array [], the original obj.search() method will be replaced with jest.fn(). You can change the value of obj.items property in each test case by assignment.

    E.g.

    obj.js:

    const obj = {
        search: () => 'real implementation',
        items: [0, 0, 0],
    };
    
    export { obj };
    

    index.test.js:

    import { obj } from './obj';
    
    jest.mock('./obj');
    
    describe('76570418', () => {
        test('should pass 0', () => {
            expect(obj.items).toHaveLength(0);
            expect(jest.isMockFunction(obj.search)).toBeTrue();
        });
        test('should pass 1', () => {
            obj.items = [1, 2, 3];
            expect(obj.items).toHaveLength(3);
            expect(jest.isMockFunction(obj.search)).toBeTrue();
        });
        test('should pass 2', () => {
            obj.items = [];
            expect(obj.items).toHaveLength(0);
            expect(jest.isMockFunction(obj.search)).toBeTrue();
        });
        test('should pass 3', () => {
            Object.assign(obj, { items: [1], a: 1 });
            expect(obj.items).toHaveLength(1);
            expect(obj.a).toBe(1);
            expect(jest.isMockFunction(obj.search)).toBeTrue();
        });
    });
    

    Test result:

     PASS  stackoverflow/76570418/index.test.js (7.347 s)
      76570418
        ✓ should pass 0 (1 ms)
        ✓ should pass 1 (1 ms)
        ✓ should pass 2
        ✓ should pass 3 (1 ms)
    
    Test Suites: 1 passed, 1 total
    Tests:       4 passed, 4 total
    Snapshots:   0 total
    Time:        7.616 s