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

ValidationError when using array in Schema #8053

Closed
BrunoGodefroy opened this issue Aug 8, 2019 · 13 comments
Closed

ValidationError when using array in Schema #8053

BrunoGodefroy opened this issue Aug 8, 2019 · 13 comments
Labels
interop issue issue with interop between Mongoose and another npm module that is not a Mongoose prod dependency
Milestone

Comments

@BrunoGodefroy
Copy link

BrunoGodefroy commented Aug 8, 2019

Do you want to request a feature or report a bug?
Report a bug

What is the current behavior?
After defining my schema similar to the following one:

const UserSchema = new mongoose.Schema({
  roles: {
    type: [String],
    index: true,
  },
});

mongoose.model('User', UserSchema)

If I try to instantiate a new User like this:

const user = new User({ roles: ['super-admin'] });

It raises the following exception ValidationError: User validation failed: roles: Cast to Array failed for value "[ 'super-admin' ]" at path "roles"

Instantiating the user with an empty roles array does not raise any exception.
This is happening on [email protected], downgrading to 5.6.8 fixes it.

If the current behavior is a bug, please provide the steps to reproduce.

The schema shown above should be enough to reproduce the issue.

What is the expected behavior?
No ValidationError exception raised when instantiating a model with an array in the schema.

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.
node 10.16.0
mongoose 5.6.9
mongo 4.0.4

@vkarpov15 vkarpov15 added this to the 5.6.10 milestone Aug 9, 2019
@vkarpov15 vkarpov15 added the has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue label Aug 9, 2019
@vkarpov15
Copy link
Collaborator

The below script executes without any error for me, please modify the below script to demonstrate your issue.

const assert = require('assert');
const mongoose = require('mongoose');

const GITHUB_ISSUE = `gh8053`;
const connectionString = `mongodb://localhost:27017/${ GITHUB_ISSUE }`;
const { Schema } = mongoose;

run().then(() => console.log('done')).catch(error => console.error(error.stack));

async function run() {
  await mongoose.connect(connectionString, { useNewUrlParser: true });
  await mongoose.connection.dropDatabase();

  console.log(mongoose.version);

  const UserSchema = new mongoose.Schema({
    roles: {
      type: [String],
      index: true,
    },
  });

  const User = mongoose.model('User', UserSchema);

  const user = new User({ roles: ['super-admin'] });

  await user.save();
}

Output:

$ node gh-8053.js 
5.6.9
(node:25883) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.
done

@vkarpov15 vkarpov15 added can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. and removed has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue labels Aug 10, 2019
@vkarpov15 vkarpov15 removed this from the 5.6.10 milestone Aug 10, 2019
@BrunoGodefroy
Copy link
Author

@vkarpov15 I have put together a small reproduction repository: https://github.com/BrunoGodefroy/repro-mongoose-issue-8053

I tried to simplify it at a maximum to showcase the error, I could not remove jest while keeping the bug so it might be caused by babel transpiling the code for jest.

Hope that helps

@Green-Cat
Copy link
Contributor

I also have this error when testing an application using mongoose schemas with arrays with jest.
Error does not occur in mongoose 5.6.7.

@xaviarnl
Copy link

I also have this error, and also with a string array. It appeared without any changes in that code for quite some time. The only difference was that I upgraded Mongoose to 5.6.9.
When I downgrade(d) to 5.6.8, the problem disappears again.

@vkarpov15 vkarpov15 added this to the 5.6.10 milestone Aug 11, 2019
@vkarpov15 vkarpov15 added has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue and removed can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. labels Aug 11, 2019
@vkarpov15
Copy link
Collaborator

This appears to be yet another bug with Jest. Not to harp about this too much, but Jest is horribly broken and you should really use Mocha or some other framework that doesn't invent its own JavaScript runtime that isn't quite Node.js or a browser. Because Jest makes up its own runtime by monkeypatching everything, code that works fine in Node.js may not work in Jest and vice versa, so Jest is not a reliable way to test Node.js projects.

It looks like this issue comes down to Jest stubbing out require(), so if you require('./) in a directory where the parent dir happens to have a file with the same name as the current directory, Jest's require() gives you the parent dir's file. For example, suppose you have the below file structure:

- test.js
- dir.js
- dir
  - index.js
  - fn.js

test.js

const fn = require('./dir/fn');

it('test', function() {
  console.log(fn());
});

dir.js

module.exports = 'top-level';

dir/index.js

module.exports = 'nested';

dir/fn.js

module.exports = function() {
  return require('./');
};

Running test.js will output:

top-level

As opposed to nested like in Node.js.

@vkarpov15 vkarpov15 added interop issue issue with interop between Mongoose and another npm module that is not a Mongoose prod dependency and removed has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue labels Aug 14, 2019
@esetnik
Copy link

esetnik commented Aug 19, 2019

Can anyone link to the relevant jest bug? It'd be good to track so that we know when we can upgrade mongoose to v5.6.9 or later.

@saifali96
Copy link

This bug has eaten up my brain today.. I'm placing orders with Postman and axios and it succeeds with the data, but fails in jest with Mongoose at 5.6.9

My test:

describe('Test the /orders/place path', () => {
	test('It should respond with 200 and oid', (done) => {
		request(app).post('/v1/orders/place')
			.send({
				key1,
				key2: true,
				key3: false,
				key4: {},
				key5: false,
				key6: ["sometext", "sometext"],
				key7: ['process it faster'],
				key8: {
					startTime: newDate,
					endTime: newDate.setHours(newDate.getHours() + 4),
				},
			})
			.set('Accept', 'application/json')
			.set('Authorization', someJWT)
			.expect('Content-Type', /json/)
			.then((response) => {
				expect(response.statusCode).toBe(200);
				expect(response.body.success).toBe(true);
				expect(typeof response.body.oid).toBe('number');
				orderID = response.body.oid;
				done();
			});
	});
});

key6 and key7 are breaking with the following error:

key7: MongooseError {
            message: 'Cast to Array failed for value "process it faster" at path "key7"',
            name: 'CastError',
            stringValue: '"process it faster"',
            kind: 'Array',
            value: 'process it faster',
            path: 'key7',
            reason: [MongooseError]
          }

^^ similarly for key6

The Mongoose model is:

...,
	key6: {
		type: [String],
	},
	ke7: {
		type: [String],
	},
...

Can someone please tell me what's wrong? Cause I don't have a clue!

@vkarpov15
Copy link
Collaborator

@saifali96 it's a bug in Jest. See this comment. I strongly recommend moving off of Jest. Jest is an anti-pattern because it does so much monkeypatching that it creates a distinct JavaScript environment that isn't quite Node.js or a browser. Code that works in Jest may not work in Node.js and vice versa.

@esetnik we'll work around this bug and similar bugs in the Mongoose code. But I strongly recommend you move off of Jest for the reasons stated above. If you're using Jest, you're not actually testing your code, you're testing how your code runs in Jest, which doesn't necessarily line up with how your code runs without Jest.

@esetnik
Copy link

esetnik commented Aug 21, 2019

I don’t think it’s necessary for mongoose to work around bugs in Jest. You’ve made it clear that Jest is not a supported test runner. I was just wondering if anyone reported this yet so that Jest can fix it. Surely if this is a bug in Jest then mongoose isn’t the only library having issues. It seems like the reproduction steps were clear enough that this could be easily reproed.

@vkarpov15
Copy link
Collaborator

I haven't reported an issue yet, but I will in the next few days. You're welcome to open up an issue in the Jest repo in the meantime.

@realeibo
Copy link

I had the same problem - I updated mongoose to 5.6.11 and it fixes it.

@saifali96
Copy link

Thanks @vkarpov15 ! I fixed it by looking at your comment. Also thanks for releasing the patch.

@vkarpov15
Copy link
Collaborator

I opened up an issue with Jest ☝️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interop issue issue with interop between Mongoose and another npm module that is not a Mongoose prod dependency
Projects
None yet
Development

No branches or pull requests

7 participants