Jasmine spyOn mongoose save

6

我希望模拟 Mongoose 模型的 save() 函数。 我想要测试的函数在名为 user.js 的文件中如下所示:

var User = import('User.js')

post: function(req, res) {
  var user = new User({
      password    : req.body.password,
      email       : req.body.email,
  });
  user.save( function(err) {
    if (err) {
      ....
    } else {
      ....
    }
  });

我尝试在另一个名为user_spec.js的文件中编写一个类似以下内容的测试:

var Hander = require('user.js')

it('works properly', function() {
  spyOn(User, 'save').andReturn(null)
  Handler.post(req, res);
});

但是这让我出现了错误:
save() method does not exist

我进行了更深入的挖掘,发现User模型本身并没有save()方法,只有实例才有。这意味着我必须模拟User的构造函数,但我在这方面遇到了很多麻烦。其他帖子提到了类似以下语句:

spyOn(window, User)

为了解决这个问题,在NodeJS中,全局对象(global)(类似于window)没有User对象,因为我将其导入为一个变量。是否可能模拟构造函数给我一个带有模拟save()方法的东西?我也看了一个名为rewire的npm模块,但我希望在处理程序中不用模拟和替换整个用户模块。


这里的信息不足,请发布您的实际代码和测试。 - user2943490
@user2943490 我已经添加了一些代码和测试。 - ritmatter
3个回答

2

这并不能解决模拟本地变量的问题,但可以解决单元测试创建新文档的问题。

在创建新文档时,最好使用Model.create()。这样可以有效地进行模拟,并且代码更简洁。正确的处理和测试方法是:

var User = import('User.js')

post: function(req, res) {
  User.create({
      password    : req.body.password,
      email       : req.body.email,
  }, function(err) {
    if (err) {
      ....
    } else {
      ....
    }
  });
});

相应的测试:

var Hander = require('user.js')

it('works properly', function() {
  spyOn(User, 'create').andReturn(null)
  Handler.post(req, res);
});

希望这个解决方法能够帮助其他在使用jasmine和mongoose进行单元测试时感到沮丧的人。


0

只有在对象创建后才能使用间谍替换函数。因此,以下代码可以正常工作:

var user = new User(…);
spyOn(user, save).…;
doSomething();

这里不会:

spyOn(User, save).…
doSomething()

当然,你可以更改mongoose内部创建对象保存函数的函数...但你可能不想去那里。


0
在一个理智的世界里,你应该能够做到这一点。
spyOn(Model.prototype, 'save')
然而,Mongoose试图过载所有的Model函数,以同时作为node.js回调和Promises。为了做到这一点,他们以一种有点难以预测的方式操纵原型,除非阅读实际的Model代码(https://github.com/Automattic/mongoose/blob/master/lib/model.js),否则很难预测。
这是一个对我实际起作用的例子。
spyOn(Model.prototype, '$__save').and.callFake(function (options, callback) { callback(); });
值得一提的是,我在应用程序代码中使用Mongoose和Promises。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接