Mongo ObjectID fails instanceof-type test in nodeunit

I ran into a minor, albeit critical, irritation when unit testing some native mongo database calls with nodeunit. Here’s a condensed and simplified version of the test I was trying to execute:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
'Save the original document to the database': function(test) {
test.expect(3);
actionModule.actions.archive({ resource: 'documents', write: true },
{ file: {
path: '/tmp/pdf.pdf',
name: 'mypdf.pdf',
type: 'application/pdf',
size: 19037,
},
}).
then(function(fileId) {
//
// PROBLEM!?!?!
//
test.ok(fileId instanceof ObjectID);
// Make sure the file model is saved
var fileSize = fs.statSync('/tmp/pdf.pdf').size;
var data = fs.readFileSync('/tmp/pdf.pdf');
GridStore.read(db, fileId, function(err, fileData) {
if (err) {
test.ok(false, err);
}
test.equal(data.toString('base64'), fileData.toString('base64'));
test.equal(data.length, fileData.length);
test.done();
});
}).
catch(function(err) {
test.ok(false, err);
test.done();
});
},

A reasonable test… process a document for archival purposes and save the original file in mongo‘s GridStore. Here, I simply wanted to ensure that the original document was actually saved and ready for retrieval. This test,

1
test.ok(fileId instanceof ObjectID);

however, kept failing. I couldn’t figure out why the fileId returned by the resolved promise was not recognized as a mongo ObjectID. This was a problem, because without a mongo ObjectID, I could not read the file back from GridStore.

A little manual investigation with the help of some console.log output didn’t lessen my confusion. First,

1
console.log(fileId);

revealed a typical ObjectID similar to this: 54a880e2644788e37a7b62ea. No problem there. But then

1
console.log(typeof fileId);

told me that the fileId variable is in fact an object. But,

1
console.log(fileId instanceof ObjectID);

insisted that fileId was most definitely not an instance of ObjectID. So then how come

1
console.log(Object.keys(fileID));

suggested that it was? The object’s keys were revealed to be [ '_bsontype', 'id' ], afterall. Something was most definitely amiss.

Having pounded my head against the wall for several hours, I finally discovered that there was an inconsistency between versions of the mongodb native node driver in the module dependencies. I ran sudo npm update and the problem resolved itself… until it broke again.

I’ll cut to the chase. Here’s the solution (from your project’s root directory):

1
2
sudo rm -rf node_modules
sudo npm install

That’s it. I’m still not 100% sure of what is going on, but here’s my theory (hoping I get the javascript/node technical jargon correct): in testing the mongo-dependent module, the ObjectID prototype used in the nodeunit test was different than the prototype that actually created the ObjectID instance (fileId in this case). I believe this situation arose as a result of adding the native mongodb driver to the main project, and then later installing a module with the same mongodb dependency. I may be proven wrong in this, and am certainly open to correction, but if I face this problem in the future, I know it can be resolved by simply removing the installed node dependencies and then reinstalling. Everything gets sorted out after that. Again:

1
2
sudo rm -rf node_modules
sudo npm install

will ensure that the ObjectID object being tested is held to scrutiny under the same mongo ObjectID prototype in the actual tests.