javascript - 完全使用 stub 测试函数

标签 javascript unit-testing testing sinon stub

过去几周我一直在编写测试。在我的工作场所,我们使用 Mocha 作为我们的测试运行器,使用 Chai 作为断言库。我也在使用 Sinon 创建 stub ,但有些事情一直困扰着我。我已经为几个函数编写了测试,在这些函数中我 stub 了函数中的每个依赖项,最糟糕的是我什至没有考虑我正在测试的函数正在接受的参数。我举个例子

module.exports = {
  "someFunc": (arg1, arg2) => {
    return new Promise((resolve, reject) => {
      Promise.all(arg1).then(data => {
        let someArray = ourHelperLib.toArray(data);
        let someObj = ourHelperLib.toObject(arg2);
          if(someArray.length == 0){
            reject("error");
          }else{
            resolve({
              "array": someArray,
              "object": someObj
            });
          }
        }).catch(err => {
            reject(err);
        });
    });
  },
}
  1. 现在,当我为此函数编写测试时,我遇到了一个情况,我将 Promise.all() stub 以抛出错误。
  2. 对于我的第二个测试,我 stub Promise.all() 以返回误报值并 stub ourHelperLib.toArray() 以抛出错误并检查函数是否处理与否。
  3. 对于我的第三次测试,我 stub Promise.all()ourHelperLib.toArray()ourHelperLib.toObject() 以返回 false肯定,然后检查输出是否已解决 promise ,其值是操作的结果。

从函数定义中可以清楚地看出,传递给函数的两个参数都直接传递给了我 stub 的依赖项,因此我可以完全忽略这些值,这就是我的意思

const stubOurHelperLibToThrowError = argFromCaller => {
    throw new Error("This is an error");
}

因为我没有处理传递给我的 stub 函数的参数,所以我根本没有根据传递给它的数据来测试函数。我只是在测试函数 someFunc() 的逻辑结构。

这是一个好的做法吗?我还没有找到很多可靠的答案,因为我负责在我目前工作的地方介绍编写单元测试的指南,所以我认为这是至关重要的。

和平!

最佳答案

您可以将 promises 传递给您的函数,而无需为您所描述的很多内容 stub 。


I have a case where I stub Promise.all() to throw error

不是 stub Promise.all,而是将一个包含被拒绝的 Promise 的数组传递给您的函数:

someFunc([Promise.reject(new Error('fail'))], null)

...这将导致 Promise.all 落入 catch 并因错误而拒绝。


I stub Promise.all() to return a false positive value and stub ourHelperLib.toArray() to throw error and check if the function handles it or not

同样,不是对 Promise.all 进行 stub ,而是传递一个包含已解析的 Promise 的数组:

someFunc([Promise.resolve('a value')], null)

您可以 stub ourHelperLib.toArray 以抛出错误,或者让您的 Promise 数组解析为您知道会导致 ourHelperLib.toArray 的内容扔。


For my third test I stub Promise.all(), ourHelperLib.toArray() and ourHelperLib.toObject() to return false positives and then check the output for a resolved promise with a value that is the resultant of the operations.

stub ourHelperLib.toArrayourHelperLib.toObject 是可选的。除非它们在计算上很昂贵(例如,如果它们进行网络调用),那么像平常一样调用它们通常是有意义的。

您可以在已解析的 Promise 数组中传递您想要提供给 ourHelperLib.toArray 的数据,只需将您想要发送的值传递给 ourHelperLib.toObject 作为第二个参数:

someFunc([
  Promise.resolve('value 1 for ourHelperLib.toArray'),
  Promise.resolve('value 2 for ourHelperLib.toArray')
], 'value for ourHelperLib.toObject')

...并检查生成的 Promise 是否解析为预期值。


一般来说,最好的做法是坚持黑盒测试。

这个函数似乎没有任何副作用,只是返回一个 Promise,它根据传递的参数解析为一个结果。

除非该函数具有计算量大的依赖项,否则最好尽可能通过简单地传递参数并验证结果来测试这样的函数。

关于javascript - 完全使用 stub 测试函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54569738/

相关文章:

javascript - HTML/CSS 本地文本文件

javascript - 无法在 UIWebView 中执行 javascript 函数?

c# - 具有相等 DateTimeOffset 日期的单元测试返回错误

java - 开启和关闭 togglz 功能的单元测试

unit-testing - 单元测试和验收测试是否足够?

testing - 如何对极其复杂的系统进行功能测试?

go - 并行运行基准测试,即模拟同时请求

swift - CloudKit 与沙箱用户同步测试

javascript - 为什么这段代码不替换每个单词的第一个字母?

javascript - AngularJs - 当范围值改变时检查条件(if - else)