2tsai 2tsai - 22 days ago 6
Node.js Question

How to stub Mongoose model constructor

I'm trying to use Sinon.js to stub the model constructor of my

Student
Mongoose model.

var Student = require('../models/student');

var student = new Student({ name: 'test student' }); // I want to stub this constructor


Looking at the Mongoose source code, Model inherits its prototype from Document, which calls the
Document
function, so this is what I tried in order to stub the constructor. However, my stub never gets called.

sinon.stub(Student.prototype__proto__, 'constructor', () => {
console.log('This does not work!');
return { name: 'test student' };
});

createStudent(); // Doesn't print anything


Thank you for any insight.

EDIT:
I can't directly set
Student()
as a stub, because I also stub
Student.find()
in another test. So my question is essentially "how do I stub
Student()
and
Student.find()
at the same time?"

Answer

It surely can be done only with sinon, but that will be very dependant on the way the lib works, and will not feel safe and maintainable.

For dependancies that are hard to mock directly, you should take a look at rewire or proxyquire (I use rewire, but you may want to have a choice) to do "monkey patching".

You will use rewire like require, but it has some sugar. Example :

var rewire = require("rewire");
var myCodeToTest = rewire("../path/to/my/code");

//Will make 'var Student' a sinon stub.
myCodeToTest.__set__('Student', sinon.stub().returns({ name: 'test'}));

//Execute code
myCodeToTest(); // or myCodeToTest.myFunction() etc..

//assert
expect...

[EDIT]

"how do I stub Student() and Student.find() at the same time?"

//Will make 'var Student' a sinon stub.
var findStub = sinon.stub().returns({});
var studentStub = sinon.stub().returns({find: findStub});
myCodeToTest.__set__('Student', studentStub);