javascriptunit-testingjestjsts-jestbabel-jest

Jest mocking of the readOnly function from dependant file


mainClass.js

import { GetData } from './childClass';

export class MainClass {
  static async execute() {
    const response = GetData();
    return response;
  }
}

childClass.js

class response {
  constructor({ data }) {
    this.data = data;
  }
}

export async function GetData() {
  return new response(data);
}

Here I'm trying to test this mainClass.js execute function using jest. And for testing I want to mock the GetData function which is part of childClass file. But here is the thing that I can't directly mock that function because GetData is read-only. I can't change that function property to read and write. So I want a way to mock this GetData function in any way.

Tried things

1)
beforeAll(() => {
  jest.mock('./childClass', () => ({
    GetData: jest.fn()
 }));
});

2)
beforeAll(() => {
  mockFunctionData = jest.spyOn(MainClass, 'GetData').mockReturnValue({});
});

None of are working. Thank you in advance.


Solution

  • First, I personally prefer spyOn, so I'll answer with it.

    When you do jest.spyOn(MainClass, 'GetData'), you are targeting the wrong thing. You want to mock the GetData function in childClass.js.

    So you need to spy on the object which contains it: not MainClass.

    And in your case, the object is a module (i.e. a file). So you have to import the module as a whole, then spy on it:

    import * as childClassModule from './childClass'
    
    // Note: `beforeAll()` won't work in some cases, depending on your Jest configuration.
    // So it's better to use `beforeEach()` in this case.
    beforeEach(() => {
      // Since your `GetData` function is async, you have to use `mockResolvedValue()`.
      jest.spyOn(childClassModule, 'GetData').mockResolvedValue({data: 'hello world'})
    })
    
    test('example', async () => {
      const result = await MainClass.execute()
      expect(result).toStrictEqual({data: 'hello world'})
    })