Jest: How can I mock a function of a Singleton?

Created on 8 Jun 2017  路  1Comment  路  Source: facebook/jest

What is the current behavior?
I'm struggling to find a way to mock a function within a Singleton Class (ES6).

Consider the following contentLoader.js

// unique key
const _contentLoaderSingleton = Symbol("contentLoaderSingleton");

/**
 * Content Loader Singleton Class
 */
class ContentLoaderSingleton {

  constructor(contentLoaderSingletonToken) {
    if (_contentLoaderSingleton !== contentLoaderSingletonToken) {
      throw new Error("Cannot instantiate directly.");
    }

    // Cached images
    this._imgLoaded = {};
    this._imgAlias = {};
  }

  static get instance() {
    if (!this[_contentLoaderSingleton]) {
      this[_contentLoaderSingleton] = new ContentLoaderSingleton(
        _contentLoaderSingleton
      );
    }

    return this[_contentLoaderSingleton];
  }

  _loadImage(path) {
    return new Promise((resolve, reject) => {
      let image = new Image();
      image.src = path;
      image.onload = () => resolve(image);
      image.onerror = () =>
        reject(new Error("Image is not defined. Unable to load it."));
    });
  }

  async loadImage(path, alias) {
    let image;
    try {
      image = await this._loadImage(path);
    } catch (error) {
      // log and rethrow
      console.error(error);
      throw error;
    }

    // cache the loaded image:
    this._imgLoaded[path] = image;

    if (alias) {
      this._imgAlias[alias] = path;
    }
  }
}

/**
 * Content Loader alias to Content Loader Singleton instance
 */
export const ContentLoader = ContentLoaderSingleton.instance;

Is there a way to mock the function _loadImage while keeping the singleton intact?

I have come across rewire (babel plugin), but if I include it in the babel plugins, it raises the following error (jest watch mode):

babel-plugin-jest-hoist: The module factory of 'jest.mock()' is not allowed to reference any out-of-scope variables.
Invalid variable access: _extends

What's the best approach here?

Thanks!

Please provide your exact Jest configuration and mention your Jest, node, yarn/npm version and operating system.
"jest": "20.0.4"
"babel-jest": "20.0.3"

Babel jest configuration:

{
  "env": {
    "test": {
      "plugins": [
        "transform-runtime",
        // "rewire"
      ],
      "presets": [
        "es2015",
        "stage-3"
      ]
    }
  }
}

Most helpful comment

It turns out to be easier than anticipated:

let ContentLoader = require.requireActual("../src/contentLoader.js").ContentLoader;

ContentLoader._loadImage = function() {
  return "teeehee";
};

module.exports = ContentLoader;

If you have any other suggestions, let me know!

Thanks

>All comments

It turns out to be easier than anticipated:

let ContentLoader = require.requireActual("../src/contentLoader.js").ContentLoader;

ContentLoader._loadImage = function() {
  return "teeehee";
};

module.exports = ContentLoader;

If you have any other suggestions, let me know!

Thanks

Was this page helpful?
0 / 5 - 0 ratings