Mongoose custom validation not working in controller

My mongoose model contains a field that is only required if the other field is equal to a specific value (i.e. it is conditional).

In this example, I have an item that has itemType 'typeA' or 'typeB'. SomeField is only required for "typeB".

In my tests, validation works when testing the model directly. However, the check is not a trigger in the controller.

My model looks like this:

var mongoose = require('mongoose'),
  Schema = mongoose.Schema;

var ItemSchema = new Schema({
  name: {
    type: String,
    trim: true,
    required: true
  },
  itemType: {
    type: String,
    enum: ['typeA', 'typeB'],
    required: true
  },
  someField: String
});

ItemSchema
  .path('someField')
  .validate(function(value, respond) {
    if (this.itemType === 'typeA') { return respond(true); }
    return respond(validatePresenceOf(value));
  }, 'someField cannot be blank for typeB');

function validatePresenceOf(value) {
  return value && value.length;
}

module.exports = mongoose.model('Item', ItemSchema);

      

In my unit test for the model:

it('should fail when saving typeB without someField', function(done) {

  var item = new Item({
    name: 'test',
    itemType: 'typeB'
  });

  item.save(function(err){
    should.exist(err);
    done();
  });

});

      

The above unit test works without issue. However, when testing the API itself, Mongoose throws no error. The controller is supposed to return a 500 error if it cannot save:

exports.create = function(req, res) {
  var item = new Item(req.body);
  item.save(function(err, data) {
    if (err) { return res.json(500, err); }
    return res.json(200, data);
  });
};

      

However, the following test always returns 200:

var request = require('supertest');

describe('with invalid fields', function() {
  it('should respond with a 500 error', function(done) {
    request(app)
      .post('/api/item')
      .send({
        name: 'test',
        itemType: 'typeB'
        })
      .expect(500)
      .end(function(err, res) {
        if (err) return done(err);
        return done();
        });
      });
  });
});

      

I'm not sure what I am doing wrong, it looks like Mongoose validation does not start when I save to controller.

+3


source to share


1 answer


The implementation is wrong here. You are not checking for "someField", but for the value passed by "itemType". The reason is that since you did not specify any value for "someField" then the validator is never called because there is nothing definite.

So, the test runs the other way around and also fixes your function validatePresenceOf()

:



itemSchema.path('itemType').validate(function(value) {
  if ( value === 'typeA' )
    return true;
  console.log( validatePresenceOf(this.someField) );
  return validatePresenceOf(this.someField);

}, 'someField cannot be blank for itemType: "typeB"');

function validatePresenceOf(value) {
  if ( value != undefined )
    return value && value.length
  else
    return false;
}

      

This will correctly throw an error: "itemType" is set to "typeB" and "someField" doesn't matter at all.

+3


source







All Articles