Jest: Jest mock module failed when mocking mongoose model object

Created on 6 Mar 2017  ยท  21Comments  ยท  Source: facebook/jest

Problem mocking a mongoose model Object with the following error.

  โ— Test suite failed to run

    TypeError: Cannot create property 'constructor' on number '1'

      at ModuleMockerClass._generateMock (node_modules/jest-mock/build/index.js:457:34)
      at Array.forEach (native)
      at Array.forEach (native)
      at Array.forEach (native)

repo with reproduction code
node - v6.9.3
yarn - v0.18.1
npm - 3.10.10
OS - macOS Sierra

Help Wanted Needs Triage

Most helpful comment

I have the same issue, how can fix it ?
@cpojer @thymikee

All 21 comments

@thymikee yes, setting testEnvironment to node doesn't fix it.

So it's probably connected with Jest running in VM context: https://github.com/facebook/jest/issues/2549

Closing as a duplicate.

@cpojer @thymikee What exactly is this a duplicate of?
I'm seeing this error right now when trying to mock mongoose models using jest. #2549 seems completely unrelated.

Yeah, I agree.

This still fails on the latest version of jest. I have no idea how or why, though ๐Ÿ˜€ The error comes from https://github.com/facebook/jest/blob/77d2e8e41ffa4a68dd7c1e3f81f5c4476c997c8a/packages/jest-mock/src/index.js#L620

+1 I have the same issue with built-in auto-mock..., but I just manually mock directly upon the method I want to stub.

I have the same issue, how can fix it ?
@cpojer @thymikee

Same here :disappointed:

Yeah, I agree.

This still fails on the latest version of jest. I have no idea how or why, though ๐Ÿ˜€ The error comes from

jest/packages/jest-mock/src/index.js

Line 620 in 77d2e8e

mock.prototype.constructor = mock;

I don't know much about Jest inner workings, but I can get my tests to run if I add a check to mock.prototype:

if (
      metadata.type !== 'undefined' &&
      metadata.type !== 'null' &&
      mock.prototype && typeof mock.prototype === 'object'
    ) {
      mock.prototype.constructor = mock;
    }

Would this break anything else? If not, then I could submit a PR if that would be helpful.

EDIT
This seems to break chaining, as I believe it's not allowing the Query object to construct itself, breaking method mocking...๐Ÿค”I may play around with this some more later and see if I can get it working

EDIT
After doing a little more digging, I'm pretty sure that line is not what causes issues with mongoose. I was able to (with the above edit) setup a mock implementation for the methods I was using and now the tests pass! Yay! So, I'm back to suggesting a PR if anyone is confident that the above change is harmless.

I have same issue. Does anyone have solution for it?

I had a look into this issue and it seems that Mongoose creates an object with a key called prototype and sets it to 1: https://github.com/Automattic/mongoose/blob/master/lib/schema.js#L464

It turns out that Jest doesn't like this. I've created a minimal repro of the problem here: https://github.com/smably/jest-prototype-test

Adding another check for typeof mock.prototype === 'object' does seem to fix this issue (thanks @hluedeke!). If no objections, I'd also be happy to open up a PR with that fix.

Using jest.mock with module factory parameter works correctly:

const Test = require('./model')

jest.mock('./model', () => {
    return {
        findOne: jest.fn(() => Promise.resolve(""))
    }
})

test("test", async () => {
    var result = await Test.findOne();

    expect(result).toBe("");
})

For some cases that might be enough.

If no objections, I'd also be happy to open up a PR with that fix.

@smably I'd be eternally grateful! I forked and updated it...but can't get all the jest tests to pass ๐Ÿ˜’ (even with periodic pulls)...so I've been hesitant to submit it

Using jest.mock with module factory parameter works correctly:

const Test = require('./model')

jest.mock('./model', () => {
    return {
        findOne: jest.fn(() => Promise.resolve(""))
    }
})

test("test", async () => {
    var result = await Test.findOne();

    expect(result).toBe("");
})

For some cases that might be enough.

I didn't know this was possible, so thanks for the info!

I'm updating this comment because the above doesn't actually address the problem. We are mocking 'mongoose' itself because if you don't mock the mongoose library, and you're using a singleton connection object, then mongoose will attempt to connect with every test suite run and will cause a jest timeout error. Mocking the whole mongoose library is the only way I've found to eliminate the connection attempt.

but can't get all the jest tests to pass ๐Ÿ˜’ (even with periodic pulls)...so I've been hesitant to submit it

What issue did you run into? I _think_ all relevant docs are in in the contributing guide.

Feel free to open up a PR and let CI run the tests though - even if they don't pass it might help someone else (or yourself) make progress on this issue ๐Ÿ™‚

This is the current error I'm getting (even with the --fix option), though the test failures have been different as I've updated jest:
image

I didn't want to go start "fixing" tests, since they aren't really related to my change, and I don't want to break something for someone else, so I've just been sitting on it.

Thanks for the encouragement @SimenB to go ahead and PR anyway. I will go ahead and submit and see what happens!

I'm updating this comment because the above doesn't actually address the problem. We are mocking 'mongoose' itself because if you don't mock the mongoose library, and you're using a singleton connection object, then mongoose will attempt to connect with every test suite run and will cause a jest timeout error. Mocking the whole mongoose library is the only way I've found to eliminate the connection attempt.

I don't know about the specifics of your code, in particular about _singleton connection object,_ but given approach where module factory is used make tests from @harin 's repo pass and in general makes it possible to mock mongoose models using jest mocks. As far as I can see the initial issue was about using auto-mocked version of mongoose model which is just exported from another module. Sorry, but I can't see how any connection object is connected with given issue.

See the repo please

I guess @leoyli 's comment was about using the same approach.

@hluedeke seems like the --fix is added to jest and not eslint... You can run yarn lint --fix and it should be fixed

I'm updating this comment because the above doesn't actually address the problem. We are mocking 'mongoose' itself because if you don't mock the mongoose library, and you're using a singleton connection object, then mongoose will attempt to connect with every test suite run and will cause a jest timeout error. Mocking the whole mongoose library is the only way I've found to eliminate the connection attempt.

I don't know about the specifics of your code, in particular about _singleton connection object,_ but given approach where module factory is used make tests from @harin 's repo pass and in general makes it possible to mock mongoose models using jest mocks. As far as I can see the initial issue was about using auto-mocked version of mongoose model which is just exported from another module. Sorry, but I can't see how any connection object is connected with given issue.

See the repo please

I guess @leoyli 's comment was about using the same approach.

You are right, my apologies. It's an old thread that I commented on months ago - I shouldn't have made assumptions. I did not mean to demean in any way - was just trying to clear up that this issue still exists when importing 'mongoose'. Didn't mean to step on any toes! ๐Ÿ˜ฌ

Fixed in #8040

Was this page helpful?
0 / 5 - 0 ratings