Search code examples
javascriptunit-testingjestjsmockingbabel-jest

Jest test case updated the mocked data object for next test case


Helpers.spec.js file

describe('Helpers', () => {
  beforeAll(() => {
    jest.clearAllMocks();

    jest.mock('./operations', () => ({
      Operators: jest.fn()
    }));
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  const mockData = [ { id: 1 }, { id: 2 }, { id: 3 } ];

  it('Should return a id 1', async () => {
    Operations.getData = jest.fn().mockResolvedValue(mockData);
    const response = await Helpers.execute();
    expect(response.id).toBe(1);
  });

  it('Should return a id 1 with true flag', async () => {
    Operations.getData = jest.fn().mockResolvedValue(mockData);
    Operations.track = jest.fn().mockResolvedValue({});

    const response = await Helpers.execute(true);
    expect(response.id).toBe(1);
  });
});

Helpers.js

import { getData, track } from `./operations`;

export class Helpers {
  static async execute(request) {
    if(request)
      track();

    const data = getData();
    return data.shift();
  }
}

Operation.js

async function getData() {
  // Operation to return the data
}

async function track() {
  // Operation to track the data
}

Here Second test case is failing because it's returning the id 2. For some reason when second test case is running at that time mockData array has been shifted once because of first test case.


Solution

    1. You should use const data = await getData(), since getData function is async.

    2. You should create the mockData for each test case so that the mutate it(data.shift()) in one test case will not affect other test cases.

    3. Put the jest.mock() in module scope of the test file.

    helpers.js:

    import { getData, track } from './operations';
    
    export class Helpers {
        static async execute(request) {
            if (request) track();
    
            const data = await getData();
            return data.shift();
        }
    }
    

    operations.js:

    export async function getData() {
        // Operation to return the data
    }
    
    export async function track() {
        // Operation to track the data
    }
    

    helpers.test.js:

    import { Helpers } from './helpers';
    import { getData, track } from './operations';
    
    jest.mock('./operations');
    
    describe('Helpers', () => {
        afterEach(() => {
            jest.clearAllMocks();
        });
    
    
        it('Should return a id 1', async () => {
        const mockData = [{ id: 1 }, { id: 2 }, { id: 3 }];
            getData.mockResolvedValue(mockData);
            const response = await Helpers.execute();
            expect(response.id).toBe(1);
        });
    
        it('Should return a id 1 with true flag', async () => {
        const mockData = [{ id: 1 }, { id: 2 }, { id: 3 }];
            getData.mockResolvedValue(mockData);
            track.mockResolvedValue({});
    
            const response = await Helpers.execute(true);
            expect(response.id).toBe(1);
        });
    });
    

    Test result:

     PASS  stackoverflow/77265044/helpers.test.js (6.052 s)
      Helpers
        ✓ Should return a id 1 (1 ms)
        ✓ Should return a id 1 with true flag
    
    Test Suites: 1 passed, 1 total
    Tests:       2 passed, 2 total
    Snapshots:   0 total
    Time:        6.261 s