完全使用存根测试函数
Testing a function entirely using stubs
过去几周我一直在编写测试。在我的工作场所,我们使用 Mocha 作为我们的测试运行器,使用 Chai 作为断言库。我也在使用 Sinon 创建存根,但有些事情一直困扰着我。我已经为几个函数编写了测试,在这些函数中我存根了函数中的每个依赖项,最糟糕的是我什至没有考虑我正在测试的函数正在接受的参数。我举个例子
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);
});
});
},
}
- 现在,当我为这个函数编写测试时,我有一个情况,我存根
Promise.all()
以抛出错误。
- 对于我的第二个测试,我存根
Promise.all()
到 return 一个误报值并存根 ourHelperLib.toArray()
抛出错误并检查函数是否处理它。
- 对于我的第三次测试,我将
Promise.all()
、ourHelperLib.toArray()
和 ourHelperLib.toObject()
存根到 return 误报,然后检查输出是否已解决,其值为操作的结果。
从函数定义中可以清楚地看出,传递给函数的两个参数都直接传递给了我存根的依赖项,因此我可以完全忽略这些值,这就是我的意思
const stubOurHelperLibToThrowError = argFromCaller => {
throw new Error("This is an error");
}
因为我没有处理传递给我的存根函数的参数,所以我根本没有根据传递给它的数据来测试函数。我只是简单地测试函数someFunc()
.
的逻辑结构
这是一个好习惯吗?我还没有找到很多可靠的答案,因为我负责在我目前工作的地方介绍编写单元测试的指南,所以我认为这是至关重要的。
和平!
您可以将 promises 传递给您的函数,而不必为您所描述的很多内容存根。
I have a case where I stub Promise.all() to throw error
而不是存根 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
,只需传递一个数组,其中包含已解析的 Promise
:
someFunc([Promise.resolve('a value')], null)
您可以存根 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.
存根 ourHelperLib.toArray
和 ourHelperLib.toObject
是可选的。除非它们在计算上很昂贵(例如,如果它们进行网络调用),那么像平常一样调用它们通常是有意义的。
你可以把你想给ourHelperLib.toArray
的数据传到已解析的Promise
数组中,把你想传给ourHelperLib.toObject
的值作为第二个参数:
someFunc([
Promise.resolve('value 1 for ourHelperLib.toArray'),
Promise.resolve('value 2 for ourHelperLib.toArray')
], 'value for ourHelperLib.toObject')
...并检查结果 Promise
是否解析为预期值。
一般来说,最好的做法是坚持黑盒测试。
此函数似乎没有任何副作用,只是 returns 一个 Promise
解析为基于传递的参数的结果。
除非该函数具有计算量大的依赖项,否则最好尽可能通过简单地传递参数并验证结果来测试这样的函数。
过去几周我一直在编写测试。在我的工作场所,我们使用 Mocha 作为我们的测试运行器,使用 Chai 作为断言库。我也在使用 Sinon 创建存根,但有些事情一直困扰着我。我已经为几个函数编写了测试,在这些函数中我存根了函数中的每个依赖项,最糟糕的是我什至没有考虑我正在测试的函数正在接受的参数。我举个例子
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);
});
});
},
}
- 现在,当我为这个函数编写测试时,我有一个情况,我存根
Promise.all()
以抛出错误。 - 对于我的第二个测试,我存根
Promise.all()
到 return 一个误报值并存根ourHelperLib.toArray()
抛出错误并检查函数是否处理它。 - 对于我的第三次测试,我将
Promise.all()
、ourHelperLib.toArray()
和ourHelperLib.toObject()
存根到 return 误报,然后检查输出是否已解决,其值为操作的结果。
从函数定义中可以清楚地看出,传递给函数的两个参数都直接传递给了我存根的依赖项,因此我可以完全忽略这些值,这就是我的意思
const stubOurHelperLibToThrowError = argFromCaller => {
throw new Error("This is an error");
}
因为我没有处理传递给我的存根函数的参数,所以我根本没有根据传递给它的数据来测试函数。我只是简单地测试函数someFunc()
.
这是一个好习惯吗?我还没有找到很多可靠的答案,因为我负责在我目前工作的地方介绍编写单元测试的指南,所以我认为这是至关重要的。
和平!
您可以将 promises 传递给您的函数,而不必为您所描述的很多内容存根。
I have a case where I stub Promise.all() to throw error
而不是存根 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
,只需传递一个数组,其中包含已解析的 Promise
:
someFunc([Promise.resolve('a value')], null)
您可以存根 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.
存根 ourHelperLib.toArray
和 ourHelperLib.toObject
是可选的。除非它们在计算上很昂贵(例如,如果它们进行网络调用),那么像平常一样调用它们通常是有意义的。
你可以把你想给ourHelperLib.toArray
的数据传到已解析的Promise
数组中,把你想传给ourHelperLib.toObject
的值作为第二个参数:
someFunc([
Promise.resolve('value 1 for ourHelperLib.toArray'),
Promise.resolve('value 2 for ourHelperLib.toArray')
], 'value for ourHelperLib.toObject')
...并检查结果 Promise
是否解析为预期值。
一般来说,最好的做法是坚持黑盒测试。
此函数似乎没有任何副作用,只是 returns 一个 Promise
解析为基于传递的参数的结果。
除非该函数具有计算量大的依赖项,否则最好尽可能通过简单地传递参数并验证结果来测试这样的函数。