0

Take the following Mongoose schema.

const userSchema = mongoose.Schema({
    username: {
        type: String,
        required: true,
        unique: true,
        minLength: 3
    },
    name: String,
    passwordHash: String
})

const User = mongoose.model('User', userSchema)

By Mongoose official documentation You can make a custom error message for each schema path as following.

 minLength: [3, 'username must be at least 3-character long']

In Node.js tests, you can easily test wrong cases as follows:

test('a user with too short username cannot be added into database', async () => {
    try {
        const user = new User({
            username: 'x'
        })
    
        await user.save()
    } catch (error) {
        expect(error.username.message).toBe('username must be at least 3-character long')
    }
})

For more readability though, I have a large validation error object, where each error is basically an object containing a message property and a code property:

const ERRORS = {
    USER: {
        USERNAME: {
            USERNAME_TOO_SHORT: {
                code: 'USERNAME_TOO_SHORT',
                message: 'Username is too short.'
            }
        }
    }
}

This way I'd only have to compare error codes in the tests not error messages:

expect(error.username.code).toBe(ERRORS.USER.USERNAME.USERNAME_TOO_SHORT.code)

The problem is mongoose does not allow "error objects" for each path:

 minLength: [3, ERRORS.USER.USERNAME.USERNAME_TOO_SHORT]

This results in [object Object] as the message, which is not useful for testing.

I'm looking for a way to test mongoose validation errors based on an error code not message. As mentioned above mongoose won't allow error objects for a schema path, it only expects strings.

1
  • As mentioned in Staging Ground, you can provide just the error code and then have a mapping of codes to full error messages (e.g. as a flat dictionary instead of nested like your current setup). This is typically how error code schemes work, like from linters, for example. Commented Nov 1 at 16:45

1 Answer 1

0

Mongoose’s built-in validation system only supports strings as error messages for path validators. When you pass an object (like your ERRORS.USER.USERNAME.USERNAME_TOO_SHORT), Mongoose calls .toString() on it, which is why you see [object Object].

But you can define a custom validator function that throws a mongoose.Error.ValidatorError with both a message and a code.

https://mongoosejs.com/docs/validation.html

Sign up to request clarification or add additional context in comments.

1 Comment

Can you explain how it's done specifically? From @agilgur5 's comment though, all I had to do was passing error codes for each path and then mapping them into error messages if necessary.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.