Jest: Fails to mock certain libraries

Created on 16 Jul 2014  路  20Comments  路  Source: facebook/jest

We ran into an issue on a project where Jest borked when requiring a certain library (in this case Bluebird http://github.com/petkaantonov/bluebird).

I set up an isolated example to see if the result was the same...

jest-issue

I wonder if it's something to do with how Bluebird is written? I'm really not sure. We resorted to overhauling our test setup because of this.

The code: https://github.com/callum/jest-issue

Seems like it could be the same issue as https://github.com/facebook/jest/issues/59

Most helpful comment

The proper solution to this problem is to put "bluebird" into the "unmockedModulePathPatterns" config.

All 20 comments

FWIW, I ran into a similar issue like this as well with ampersand-state except an "undefined is not a function" error. Had to add it to the dont mock section in package.json

Ran into similar issues with the mongoose & winston modules compounded by issue #110 which stomps on the console output when the process dies so that the errors weren't clear.

https://www.npmjs.org/package/mongoose
https://www.npmjs.org/package/winston

I understand that configuring these modules not to be mocked would get me around the exceptions, however, these are libraries that I need to mock in order to test the smallest unit of relevant code in my code base. I was hoping that jest would keep me from having to do the work of manually mocking these types of dependencies, but resorted to doing just that.

image

image

I have simular problems loading joi:

This happens with jest.dontMock('joi') and without it.

TypeError: c:\Workspace\synductis\test\testJest.js: c:\Workspace\synductis\node_modules\joi\index.js: c:\Workspace\synductis\node_modules\joi\lib\index.js: c:\Workspace\synductis\node_modules\joi\lib\cast.js: c:\Workspace\synductis\node_modules\joi\lib\date.js: Property 'inherits' of object [object Object] is not a function
    at c:\Workspace\synductis\node_modules\joi\lib\date.js:19:6
    at Object.runContentWithLocalBindings (c:\Workspace\synductis\node_modules\jest-cli\src\lib\utils.js:315:17)
    at Loader._execModule (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:243:9)
    at Loader.requireModule (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:886:12)
    at Loader._generateMock (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:274:30)
    at Loader.requireMock (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:790:43)
    at Loader.requireModuleOrMock (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:905:17)
    at c:\Workspace\synductis\node_modules\joi\lib\cast.js:12:11
    at Object.runContentWithLocalBindings (c:\Workspace\synductis\node_modules\jest-cli\src\lib\utils.js:315:17)
    at Loader._execModule (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:243:9)
    at Loader.requireModule (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:886:12)
    at Loader._generateMock (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:274:30)
    at Loader.requireMock (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:790:43)
    at Loader.requireModuleOrMock (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:905:17)
    at c:\Workspace\synductis\node_modules\joi\lib\index.js:5:12
    at Object.runContentWithLocalBindings (c:\Workspace\synductis\node_modules\jest-cli\src\lib\utils.js:315:17)
    at Loader._execModule (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:243:9)
    at Loader.requireModule (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:886:12)
    at Loader._generateMock (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:274:30)
    at Loader.requireMock (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:790:43)
    at Loader.requireModuleOrMock (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:905:17)
    at c:\Workspace\synductis\node_modules\joi\index.js:1:85
    at Object.runContentWithLocalBindings (c:\Workspace\synductis\node_modules\jest-cli\src\lib\utils.js:315:17)
    at Loader._execModule (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:243:9)
    at Loader.requireModule (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:886:12)
    at Loader.requireModuleOrMock (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:907:17)
    at c:\Workspace\synductis\test\testJest.js:4:11
    at Object.runContentWithLocalBindings (c:\Workspace\synductis\node_modules\jest-cli\src\lib\utils.js:315:17)
    at Loader._execModule (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:243:9)
    at Loader.requireModule (c:\Workspace\synductis\node_modules\jest-cli\src\HasteModuleLoader\HasteModuleLoader.js:886:12)
    at jasmineTestRunner (c:\Workspace\synductis\node_modules\jest-cli\src\jasmineTestRunner\jasmineTestRunner.js:225:16)
    at c:\Workspace\synductis\node_modules\jest-cli\src\TestRunner.js:370:12
    at _fulfilled (c:\Workspace\synductis\node_modules\jest-cli\node_modules\q\q.js:798:54)
    at self.promiseDispatch.done (c:\Workspace\synductis\node_modules\jest-cli\node_modules\q\q.js:827:30)
    at Promise.promise.promiseDispatch (c:\Workspace\synductis\node_modules\jest-cli\node_modules\q\q.js:760:13)
    at c:\Workspace\synductis\node_modules\jest-cli\node_modules\q\q.js:574:44
    at flush (c:\Workspace\synductis\node_modules\jest-cli\node_modules\q\q.js:108:17)
    at c:\Workspace\synductis\node_modules\jest-cli\src\lib\FakeTimers.js:259:7
    at process._tickCallback (node.js:419:13)

I've the same problem loading the wreck module as @tcoopman, with or without dontMock.

Looking at the code for joi and for wreck, I see that the "Property 'inherits'鈥s not a function" bit is triggered in both cases by a call to Hoek.inherits, such as from joi source:

Hoek.inherits(internals.Date, Any);

I also tried dontMock on hoek, but that didn't change things, either.

I'm guessing the only workaround is a manual mock in here somewhere?

@tcoopman I was able to get wreck to mock properly after adding the following bits to my test:

jest.dontMock( "util" );
jest.dontMock( "hoek" );
jest.dontMock( "https" );
jest.dontMock( "http" );

Presumably you wouldn't need the http* lines for joi, but I'm pretty sure you'll need at least the first two lines.

Regarding my previous comment about mocking joi: While my mock for wreck works fine, turns out mocking joi is a completely different beast, and my suggestion above doesn't work. At the very least, I've been able to get require('joi') not to mess up my other tests (that don't use joi), but that's about it:

jest.dontMock('net');
jest.dontMock('isemail');
jest.dontMock('topo');
jest.dontMock('moment');
jest.dontMock('../../node_modules/joi/index.js');
jest.dontMock('../../node_modules/joi/lib/any.js');
jest.dontMock('../../node_modules/joi/lib/array.js');
jest.dontMock('../../node_modules/joi/lib/binary.js');
jest.dontMock('../../node_modules/joi/lib/boolean.js');
jest.dontMock('../../node_modules/joi/lib/cast.js');
jest.dontMock('../../node_modules/joi/lib/date.js');
jest.dontMock('../../node_modules/joi/lib/errors.js');
jest.dontMock('../../node_modules/joi/lib/function.js');
jest.dontMock('../../node_modules/joi/lib/index.js');
jest.dontMock('../../node_modules/joi/lib/language.js');
jest.dontMock('../../node_modules/joi/lib/number.js');
jest.dontMock('../../node_modules/joi/lib/object.js');
jest.dontMock('../../node_modules/joi/lib/ref.js');
jest.dontMock('../../node_modules/joi/lib/string.js');

Is there a cleaner way to do that?

I've tried quite a few things with dontMock and config.unmockedModulePathPatterns, but have had no success. With that code, the test errors with

 TypeError: Object [object Object] has no method 'required'

when I have Joi.string().required() in the schema.

Has anyone been successful testing code that uses joi with Jest?

cc: @tcoopman

FWIW, I did get joi to mock correctly. I had to add a few more dontMock's for hoek:

jest.dontMock('net');
jest.dontMock('isemail');
jest.dontMock('topo');
jest.dontMock('moment');
jest.dontMock('../../node_modules/joi/index.js');
jest.dontMock('../../node_modules/joi/lib/any.js');
jest.dontMock('../../node_modules/joi/lib/array.js');
jest.dontMock('../../node_modules/joi/lib/binary.js');
jest.dontMock('../../node_modules/joi/lib/boolean.js');
jest.dontMock('../../node_modules/joi/lib/cast.js');
jest.dontMock('../../node_modules/joi/lib/date.js');
jest.dontMock('../../node_modules/joi/lib/errors.js');
jest.dontMock('../../node_modules/joi/lib/function.js');
jest.dontMock('../../node_modules/joi/lib/index.js');
jest.dontMock('../../node_modules/joi/lib/language.js');
jest.dontMock('../../node_modules/joi/lib/number.js');
jest.dontMock('../../node_modules/joi/lib/object.js');
jest.dontMock('../../node_modules/joi/lib/ref.js');
jest.dontMock('../../node_modules/joi/lib/string.js');
jest.dontMock('../../node_modules/joi/node_modules/hoek/index.js');
jest.dontMock('../../node_modules/joi/node_modules/hoek/lib/index.js');
jest.dontMock('../../node_modules/joi/node_modules/hoek/lib/escape.js');

+1

Getting error:

// in node_modules/bluebird/js/main/bluebird.js
Cannot set property 'noConflict' of undefined

And if I dontMock everything under bluebird, I get segmentation fault

$ jest
Using Jest CLI v0.4.0
Waiting on 1 test...Segmentation fault: 11
$

and I do this

jest
    .dontMock('bluebird')
    .dontMock('../node_modules/bluebird/js/main/any.js')
    .dontMock('../node_modules/bluebird/js/main/assert.js')
    .dontMock('../node_modules/bluebird/js/main/async.js')
    .dontMock('../node_modules/bluebird/js/main/bind.js')
    .dontMock('../node_modules/bluebird/js/main/bluebird.js')
    // ...
    .dontMock('../node_modules/bluebird/js/main/using.js')
    .dontMock('../node_modules/bluebird/js/main/util.js')

I also have problem working with bluebird. Same error message. (related https://github.com/facebook/react-native/pull/516#issuecomment-87887208)

FYI here is what I did to work around the problem. In my project root I have a file in __mocks__/bluebird.js

'use strict';

jest.autoMockOff();
module.exports = require.requireActual('bluebird');
jest.autoMockOn();

@amasad Thanks, this workaround is working for me.

@amasad workaround also worked for me :+1:

Thank you for reporting this issue and appreciate your patience. We've notified the core team for an update on this issue. We're looking for a response within the next 30 days or the issue may be closed.

@amasad thank you for the workaround.

Any update on this? I'm running into this problem when using a symlink in node_modules.

Thank you for reporting this issue and appreciate your patience. We've notified the core team for an update on this issue. We're looking for a response within the next 30 days or the issue may be closed.

Could _we_ get a response from _you_, please?

Certainly! Unfortunately it is hard to auto-mock something at runtime that uses meta-programming for its implementation without ES2015 Proxies which aren't properly implemented in any engine yet. For these cases there are always two solutions:

  • Create a manual mock instead
  • Do not mock that module at all

In a lot of cases you don't actually want mocking. You probably always want an unmocked version of bluebird; there is no point in mocking a Promise library.

The proper solution to this problem is to put "bluebird" into the "unmockedModulePathPatterns" config.

See my last comment in #471. The documentation is also improved in #763.

Was this page helpful?
0 / 5 - 0 ratings