Question

I'm having trouble getting jasmine spies to work for my mongoose documents. I have a method set up in my User schema like so:

User.methods.doSomething = function() {
   // implementation
}

User is a dependency of the model I'm currently testing and I want to ensure that doSomething is being called correctly. In my tests I have something like:

spyOn(User.schema.methods, 'doSomething')

If I log out User.schema.methods.doSomething I get the function I expect but when I run the code that calls that method the original implementation is invoked and not the spy. Also I can't do:

spyOn(userInstance, 'doSomething')

In my tests as the userInstance isn't being exposed and I really want to avoid exposing it. Essentially I want to set up a spy on the User document (instance?) prototype. Is that possible?

Était-ce utile?

La solution

Mongoose is copying the methods defined in the schema to the model prototype and only those methods are used. So even though

User.schema.methods.doSomething === User.prototype.doSomething

if you set:

spyOn(User.schema.methods, 'doSomething')

it won't get called - User.prototype.doSomething will. Your guess was right, you should just use:

spyOn(User.prototype, 'doSometing');

Don't forget to use and.callThrough if you want to have the original method called after setting up the spy (I fell for that).

Autres conseils

Unfortunately, I couldn't get the spyOn to work on the model prototype. It might be because my 'model' is actually a mongoose subdocument.

Instead I opted for a proxy function, which I spyOn instead. It's an extra function call, which is a bit annoying, but it works.

// index.js
Controller._performClone = function(doc) {
  return doc.clone();
};

Controller.clone = function(id) {
  var child = parent.children.id(req.params.id);
  return Controller._performClone(child);
};


// spec.js
describe('Cloning', function() {
  it('should clone a document', function(done) {
    spyOn(Controller, '_performClone').and.returnValue('cloned');
    var rtn = Controller.clone('1');
    expect(rtn).toBe('cloned');

    // `correctChild` is the one you expect with ID '1'
    expect(Controller._performClone).toHaveBeenCalledWith(correctChild);
  });
});
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top