在被测试的方法中模拟一个函数

时间:2016-03-17 16:06:51

标签: javascript node.js unit-testing testing mocking

我想在我的代码中测试一个执行一组不同函数的方法......并在调用时调用其中一个内部函数,发送一封电子邮件。

我想要的是避免此功能在运行测试时发送电子邮件。有没有办法实现这个目标?

我想在我的代码中逃避以下内容:

if (app.get('env') !== 'test')

我使用 Promises ,我想测试的功能如下:

var emailService = require('../path/to/custom/service.js');

// This is the method I want to test
exports.sendKeyByEmail = function(email) {
  return _getByEmail(email) // finds a user given an email
    .then(function(user) {
      if (!user) {
        throw new UserNotFoundError();
      }
      user.key = _generateKey(); // generates a random hash
      return user.save(); // saves the user (mongoose stuff...)
    })
    .then(function(user) {
      // This is what I would like to mock during testing
      return emailService.sendKey(user.email, user.key);
    });
}

emailService.sendKey()方法是发送电子邮件并返回Promise的方法。在测试期间,我希望它直接返回一个已完成的Promise Promise.resolve(),而不是真正发送电子邮件。

1 个答案:

答案 0 :(得分:1)

I answered a question just like this yesterday:不是将两个关注点合并到私有方法或隐藏函数中,而是将它们分成两个类,并将电子邮件实现传递给外部类。这将允许您在测试期间提供模拟emailService并且非常巧妙地解决您的问题。

当设置它时,我是构造函数依赖注入的粉丝,因为它为你提供了DI的好处而没有做任何棘手的事情(比如反射)。使用ES6参数,您还可以在不嘲笑任何内容时提供默认值。

非常粗略地说,你可以这样做:

var defaultEmailService = require('../path/to/custom/service.js');

// This is the method I want to test
exports.sendKeyByEmail = function(email, emailService = defaultEmailService) {
  return _getByEmail(email) // finds a user given an email
    .then(function(user) {
      if (!user) {
        throw new UserNotFoundError();
      }
      user.key = _generateKey(); // generates a random hash
      return user.save(); // saves the user (mongoose stuff...)
    })
    .then(function(user) {
      // This is what I would like to mock during testing
      return emailService.sendKey(user.email, user.key);
    });
}

在您的测试中,只需传递一个模拟emailService,它可以在不触及网络的情况下返回可预测的结果。