Jest: Remocking mocked module

Created on 20 Nov 2016  路  2Comments  路  Source: facebook/jest

Hello everyone,

i would like to request a feature, if it is not implemented yet.
i just stared testing with jest and asked myself how to test an express application efficiently.

What is the current behavior?
I wanted to write the tests on 2 points:

  1. When the application talks to my mongoose model

  2. When the application answers the request

So i wrote following code:

describe("GET route", function() {
    // Preperation
    // Mocking express req and res
    var httpMocks = require.requireActual("node-mocks-http");

    var req = httpMocks.createRequest({
        method: 'GET',
        url: '/'
    });
    var res = httpMocks.createResponse({
        eventEmitter: require('events').EventEmitter
    });

    //Tests
    //Testing the default request
    it('tests the empty req', (done) => {
        jest.mock("../model/mymongoosemodel", function() {
            return function() {
                //mocking the behavior of the mongoose model (find and sort => chainable) returning a promise
                var model = function() {};
                model.find = function() {
                    var prom = new Promise(function(resolve, reject) {
                        resolve([]);
                    });
                    prom.sort = function() {
                        //writing my expect statements
                        expect(arguments[0]).toBeDefined();

                        return prom;
                    };

                    return prom;
                };
                return model;
            };
        });

        res.on('end', function() {
            var data = res._getData();
            expect(res.statusCode).toBe(200);
            expect(data).toBeDefined();
            done();
        });
        require("myroute")(req, res);
    });

    //Tests
    //Testing the skip request
    it('tests the skip req', (done) => {
        jest.mock("../model/mymongoosemodel", function() {
            return function() {
                 //mocking the behavior of the mongoose model (find sort and skip => chainable) returning a promise
                var model = function() {};
                model.find = function() {
                    var prom = new Promise(function(resolve, reject) {
                        resolve([]);
                    });
                    prom.skip = function() {
                        return prom;
                    };
                    prom.sort = function() {
                        expect(arguments[0]).toBeDefined();
                        return prom;
                    };

                    return prom;
                };
                return model;
            };
        });

        res.on('end', function() {
            var data = res._getData();
            expect(res.statusCode).toBe(200);
            expect(data).toBeDefined();
            done();
        });

        req.url += "10";
        require("myroute")(req, res);
    });
});

What is the expected behavior?

If i run this, the second test fails because there is no skip in my mongoose model.
I analyzed that and found that the second jest.mock call on ../model/mymongoosemodel did not override the first one.

So now my question:

Is it possible to do something like a remock on already mocked modules?

Thanks in advance

jpolack

Run Jest again with --debug and provide the full configuration it prints. Please mention your node and npm version and operating system.

jest version = 17.0.3
test framework = jasmine2
config = {
  "testPathDirs": [
    "/Users/jpolack/workspace/Server/__tests__"
  ],
  "setupTestFrameworkScriptFile": "/Users/jpolack/workspace/Server/testapp.js",
  "rootDir": "/Users/jpolack/workspace/Server",
  "name": "-Users-jpolack-workspace-Server",
  "setupFiles": [],
  "testRunner": "/usr/local/lib/node_modules/jest/node_modules/jest-cli/node_modules/jest-jasmine2/build/index.js",
  "automock": false,
  "bail": false,
  "browser": false,
  "cacheDirectory": "/var/folders/1n/wqmw_88514g656zcmvsp0gvc0000gn/T/jest",
  "coveragePathIgnorePatterns": [
    "/node_modules/"
  ],
  "coverageReporters": [
    "json",
    "text",
    "lcov",
    "clover"
  ],
  "expand": false,
  "globals": {},
  "haste": {
    "providesModuleNodeModules": []
  },
  "mocksPattern": "__mocks__",
  "moduleDirectories": [
    "node_modules"
  ],
  "moduleFileExtensions": [
    "js",
    "json",
    "jsx",
    "node"
  ],
  "moduleNameMapper": {},
  "modulePathIgnorePatterns": [],
  "noStackTrace": false,
  "notify": false,
  "preset": null,
  "resetMocks": false,
  "resetModules": false,
  "snapshotSerializers": [],
  "testEnvironment": "jest-environment-jsdom",
  "testPathIgnorePatterns": [
    "/node_modules/"
  ],
  "testRegex": "(/__tests__/.*|\\.(test|spec))\\.jsx?$",
  "testURL": "about:blank",
  "timers": "real",
  "transformIgnorePatterns": [
    "/node_modules/"
  ],
  "useStderr": false,
  "verbose": null,
  "watch": false,
  "cache": true,
  "watchman": true
}

Most helpful comment

If you'd like to mock a module that was previously required, you'll have to call jest.resetModules() and re-require it.

Example:

let module = require('module');
jest.mock('module');
jest.resetModules();
module = require('module'); // this is a fresh, mocked copy

in beforeEach that may look like this:

let module;
beforeEach(() => {
  jest.mock('module');
  jest.resetModules();
  module = require('module'); // this is a fresh, mocked copy
});

All 2 comments

I'm interested on this as well... I'd lke to be able to mock modules only for specific asserts, like this:

describe('', () => {
  it('',() => {
    jest.mock('module', () => {});
    // here `module` will be mocked
  })

  it('',() => {
    // here `module` points to its original source
  })
})

I'm not sure if that's already supported though, but I looked in the docs, and were not able to find anything related to it :(

If you'd like to mock a module that was previously required, you'll have to call jest.resetModules() and re-require it.

Example:

let module = require('module');
jest.mock('module');
jest.resetModules();
module = require('module'); // this is a fresh, mocked copy

in beforeEach that may look like this:

let module;
beforeEach(() => {
  jest.mock('module');
  jest.resetModules();
  module = require('module'); // this is a fresh, mocked copy
});
Was this page helpful?
0 / 5 - 0 ratings