【问题标题】:Mocking a function inside the method being tested在被测试的方法中模拟一个函数
【发布时间】:2016-07-04 02:48:13
【问题描述】:

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

我想要的是避免此功能在运行测试时发送电子邮件。有没有办法做到这一点?

我想在我的代码中避开类似以下内容:

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(),而不是真正发送电子邮件。

【问题讨论】:

  • 这种问题可以通过依赖注入解决——在你的测试中,你将emailService 的真实实现换成一个假装它已经发送邮件的实现。
  • @Starscream1984 这就是我想到的概念,谢谢指出!

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


【解决方案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 即可返回可预测的结果,而无需接触网络。

【讨论】:

  • 我只是想知道...这听起来很适合进行单元测试,但是 API 测试呢?假设我想测试我的 API 方法(使用 superset)来检查正确的响应 http 代码,并且我还想模拟 emailService ... 因为我没有测试直接调用它的 sendEmail() 方法,这会不会也可以吗?你明白我的意思吗? :-)
  • @charliebrownie 模拟出你的 API 对小型测试(单元测试)很有好处。您偶尔可以模拟(或代理)API 使用的网络类并测试错误处理,但您可能需要设置 API 的测试实例或类似的东西以进行更大的测试(集成测试)。
猜你喜欢
  • 1970-01-01
  • 2011-10-30
  • 1970-01-01
  • 2015-12-17
  • 2021-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多