Question

I am trying to test my custom method on my Mongoose model, but the value I set in the test model disappears and makes the test fail. The test looks like this:

it('should get the friend id', function(){
    var conversation = new Conversation({
        'users': [new ObjectId('0'), new ObjectId('1')]
    });

    expect(conversation.getFriendId('0')).toEqual(new ObjectId('1'));
});

My model declaration contains this:

var mongoose = require('mongoose');
var ObjectId = mongoose.Schema.Types.ObjectId;

var ConversationSchema = new mongoose.Schema({
    'users': [{'type': ObjectId, 'ref': 'User'}]
});

ConversationSchema.methods.getFriendId = function(userId) {
    return this.users;
    //return this.users[0] === new ObjectId(userId)
    //    ? this.users[1] : this.users[0];
};

module.exports = mongoose.model('Conversation', ConversationSchema);

When I run the test, I get:

Expected [  ] to equal { path : '1', instance : 'ObjectID', validators : [  ], setters : [  ], getters : [  ], options : undefined, _index : null }.

I set the users in the test, so the return value should be the array of users. (Which will still fail the test in it's current state, but should theoretically pass when uncommenting the second return statement.) Instead the users array shows up as empty.

How do I get the value from the test model to appear in my custom function?

Was it helpful?

Solution

I changed a number of things to get this to finally work.

I changed the users array to a set-like object because it was a more accurate representation of the data. The keys for the set are the strings for the ObjectId.

To create a new ObjectId, you must have either a 12 byte string or a 24 character hex string. Originally, I tried to do it with a single digit string. I added a spec helper that stores dummy ids with 24 character hex strings.

mongoose.Schema.Types.ObjectId and mongoose.Types.ObjectId are two different things. I tried each one before realizing I needed to use both. When creating the Schema, I need mongoose.Schema.Types.ObjectId. Any other time I'm referring to the type ObjectId, I need mongoose.Types.ObjectId.

I was trying to return the model from the files where I define them to access them. Instead I needed to call mongoose.model() to get my models.

With these changes, my model definition now looks like this:

var mongoose = require('mongoose');
var ObjectId = mongoose.Schema.Types.ObjectId;

var ConversationSchema = new mongoose.Schema({
    'users': Object,
    'messages': [
        {
            'text': String,
            'sender': {'type': ObjectId, 'ref': 'User'}
        }
    ]
});

ConversationSchema.methods.getFriendId = function(userId) {
    for (var u in this.users) {
        if (u !== userId) return new mongoose.Types.ObjectId(u);
    }

    return null;
};

// other custom methods...

mongoose.model('Conversation', ConversationSchema);

My test looks like this:

describe('getFriendId()', function(){
    var mongoose = require('mongoose');
    var ObjectId = mongoose.Types.ObjectId;

    require('../../../models/Conversation');
    var Conversation = mongoose.model('Conversation');

    var helper = require('../spec-helper');

    it('should get the friend id', function(){
        users = {};
        users[helper.ids.user0] = true;
        users[helper.ids.user1] = true;

        var conversation = new Conversation({ 'users': users });

        expect(conversation.getFriendId(helper.ids.user0)).toEqual(new ObjectId(helper.ids.user1));
    });
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top