Search code examples
node.jsjestjses6-promise

jest.spyOn method that return a Promise


I'm trying to test an application but jest.spyOn is make me crazy.

I'm working on node v8.9.4 and jest v22.2.2

I have extracted this code:

// my-module.js
class MySingletonModule {
  constructor() {
    this.foo = 'bar';
  }
  myPromise() {
    return new Promise((resolve, reject) => resolve(this.foo));
  }
}

module.exports = new MySingletonModule();

// promise.test.js
const singleton = require('./my-module');
describe('Module test-suite', () => {
  let spy;

  beforeAll(async () => {
    spy = jest.fn();
    spy = jest.spyOn(singleton, 'myPromise');
  });

  beforeEach(() => spy.mockReset());

  test('Check bar', () => {
    return singleton.myPromise().then((bar) => {
      expect(bar).toEqual('bar');
    });
  });

  test('Check called times', () => {
    singleton.myPromise();
    expect(spy).toHaveBeenCalledTimes(1);
  });

  afterAll(() => {
    jest.restoreAllMocks();
  });
});

The Check bar test is failing because the myPromise method doesn't return a promise:

the error

If I comment the spy = jest.spyOn(singleton, 'myPromise'); the test works.. but obviously the other test doesn't works..

enter image description here

I would expect that all the tests work with spyOn, because reading the docs is wrote:

Note: By default, jest.spyOn also calls the spied method.

I'm missing something?

Thanks for the help


Solution

  • Here is working snippet without Jasmine:

    describe('Module test-suite', () => {
      let spy;
    
      beforeAll(() => { // get rid of async
        spy = jest.fn();
        spy = jest.spyOn(singleton, 'myPromise');
      });
    
      afterEach(() => spy.mockRestore()); // main difference is here
    
      test('Check bar', () => {
        return singleton.myPromise().then((bar) => {
          expect(bar).toEqual('bar');
        });
      });
    
      test('Check called times', () => {
        singleton.myPromise();
        expect(spy).toHaveBeenCalledTimes(1);
      });
    
      afterAll(() => {
        jest.restoreAllMocks();
      });
    });
    

    I think it's better to use mockRestore instead of mockReset, because as I understand from jest docs mockReset hardly clears all information about spy and spying object. And mockRestore just clears some temp data such as number of called times.

    Why is using afterEach instead of beforeEach important - I have no clue :(

    Also I removed async because tests failed with it.