How can I spy on a function that is returned by a other function with Jest spyOn

278 Views Asked by At

I wonder why the last assert (expect(msgSpy).toBeCalled()) in this example fails. What do I need to change to make it pass?

  it('spyOn test', () => {
    const newClient = () => {
      const getMsg = () => {
        return 'dear spyOn';
      };
      const getHello = () => {
        return `Hello, ${getMsg()}`;
      };
      return {
        getMsg,
        getHello,
      };
    };

    const c = newClient();
    const helloSpy = jest.spyOn(c, 'getHello');
    const msgSpy = jest.spyOn(c, 'getMsg');

    expect(c.getHello()).toEqual('Hello, dear spyOn');

    expect(helloSpy).toBeCalled(); // asserts to true
    expect(msgSpy).toBeCalled();   // <-- asserts to false!
  });
1

There are 1 best solutions below

0
Faber On

Spying works if we access getMsg in getHello through the object that we spy on. Hence, a possible solution could be:

it('spyOn test', () => {
  const newClient = () => {
    const getMsg = () => {
      return 'dear spyOn';
    };
    const r = {
      getMsg,
      getHello: () => {
        return `Hello, ${r.getMsg()}`;
      },
    };

    return r;
  };

  const c = newClient();
  const helloSpy = jest.spyOn(c, 'getHello');
  const msgSpy = jest.spyOn(c, 'getMsg');

  expect(c.getHello()).toEqual('Hello, dear spyOn');

  expect(helloSpy).toBeCalled(); // asserts to true
  expect(msgSpy).toBeCalled(); // <-- asserts to true now!
});