Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jest mock module failed when mocking mongoose model object #3073

Closed
harin opened this issue Mar 6, 2017 · 22 comments
Closed

Jest mock module failed when mocking mongoose model object #3073

harin opened this issue Mar 6, 2017 · 22 comments

Comments

@harin
Copy link

harin commented Mar 6, 2017

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

@thymikee
Copy link
Collaborator

thymikee commented Mar 6, 2017

Does it happen on node environment? http://facebook.github.io/jest/docs/configuration.html#testenvironment-string

@harin
Copy link
Author

harin commented Mar 6, 2017

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

@thymikee
Copy link
Collaborator

thymikee commented Mar 6, 2017

So it's probably connected with Jest running in VM context: #2549

@cpojer
Copy link
Member

cpojer commented Mar 6, 2017

Closing as a duplicate.

@cpojer cpojer closed this as completed Mar 6, 2017
@kaitlynbrown
Copy link

@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.

@SimenB
Copy link
Member

SimenB commented May 23, 2018

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

@leoyli
Copy link

leoyli commented May 26, 2018

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

@Dimatymoshchenko
Copy link

Dimatymoshchenko commented Aug 27, 2018

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

@raryson
Copy link

raryson commented Sep 25, 2018

Same here 😞

@hluedeke
Copy link
Contributor

hluedeke commented Oct 2, 2018

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.

hluedeke pushed a commit to hluedeke/jest that referenced this issue Oct 18, 2018
@phongever
Copy link

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

@smably
Copy link

smably commented Mar 4, 2019

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.

@vitaliyazvinski
Copy link
Contributor

vitaliyazvinski commented Mar 4, 2019

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.

@hluedeke
Copy link
Contributor

hluedeke commented Mar 4, 2019

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

@hluedeke
Copy link
Contributor

hluedeke commented Mar 4, 2019

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.

@SimenB
Copy link
Member

SimenB commented Mar 4, 2019

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 🙂

@hluedeke
Copy link
Contributor

hluedeke commented Mar 4, 2019

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!

@vitaliyazvinski
Copy link
Contributor

vitaliyazvinski commented Mar 4, 2019

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.

@SimenB
Copy link
Member

SimenB commented Mar 4, 2019

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

@hluedeke
Copy link
Contributor

hluedeke commented Mar 4, 2019

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! 😬

@SimenB
Copy link
Member

SimenB commented Mar 4, 2019

Fixed in #8040

@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 12, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests