Jest: Mocking static class methods

Created on 5 Jul 2016  ·  3Comments  ·  Source: facebook/jest

I ran into an issue trying to mock a static class method in Jest. Is this behavior supported?

Cross-posted at http://stackoverflow.com/questions/38206478/mocking-methods-in-jest

I have a very simple unit test that looks like this:

import ApiWrapper from '../../services/api_wrapper';
jest.unmock('../helper')

describe('Helper', () => {
    let Helper;

    beforeEach(() => {
        Helper = require('../helper').default;
    });

    it('calls the Api Wrapper', () => {
        Helper.help()

        expect(ApiWrapper.help).toHaveBeenCalled();
    });

});

Where Helper looks like this:

import ApiWrapper from '../services/api_wrapper'
class Helper {
    help() {
        ApiWrapper.help()
    }
}

export default new Helper();

And ApiWrapper looks like this:

class ApiWrapper {
  static help () {
     console.log('help!')
  }
}
export default ApiWrapper;

ApiWrapper.help() gets mocked by Jest so 'help!' never gets printed, yet the expectation in the test fails. This still fails if we rewrite ApiWrapper to just be a plain Javascript object like such:

export default {
    help: () => { console.log('help!'); }
}

It works, however, if we change the imports in the spec (so ApiWrapper is imported in the beforeEach), and rewrite ApiWrapper to be a Singleton class, like so:

class ApiWrapper {
   help() {
      console.log('help!');
   }
}();

export default new ApiWrapper();

What is it about Jest's mocking behavior that makes this happen?

Most helpful comment

Jest resets the module registry on every call to it. You are requiring ApiWrapper on the top and Helper inside beforeEach, so Helper likely receives a different copy of ApiWrapper. To fix it you can:

  • Import both classes on the top.
  • Require both classes in beforeEach

Simplified explanation:

var A = require('A');
jest.resetModuleRegistry();
A !== require('A'); // true, A is not the exact same module as before we reset the registry.

Let me know if that doesn't fix your problem.

All 3 comments

The correct assertion should be toBeCalled. Can you try that?

Sorry, that's what I meant. I typed the example in Stackoverflow directly.

Jest resets the module registry on every call to it. You are requiring ApiWrapper on the top and Helper inside beforeEach, so Helper likely receives a different copy of ApiWrapper. To fix it you can:

  • Import both classes on the top.
  • Require both classes in beforeEach

Simplified explanation:

var A = require('A');
jest.resetModuleRegistry();
A !== require('A'); // true, A is not the exact same module as before we reset the registry.

Let me know if that doesn't fix your problem.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kentor picture kentor  ·  3Comments

StephanBijzitter picture StephanBijzitter  ·  3Comments

mmcgahan picture mmcgahan  ·  3Comments

ianp picture ianp  ·  3Comments

ticky picture ticky  ·  3Comments