想象我有功能
foo()
:
var foo = function(string) {
return string.replace(/a/g, '');
};
我对其进行了以下测试:
foo()
存在;foo()
从字符串中剥离 a
,并且对没有 a
的字符串不执行任何操作;foo()
会抛出TypeError
;问题出在测试#3上——然而它从一开始就是绿色的,这不是我的优点。我希望写出这样的东西:
var foo = function(string) {
if (typeof string !== 'string') {
throw new TypeError('argument should be a string');
}
return string.replace(/a/g, '');
};
但我不能,因为没有测试。所以
foo()
确实会抛出 TypeError,但不是因为参数类型错误,而是因为作为参数给出的 null、未定义、数字、数组、布尔值、正则表达式等对象不提供 replace()
方法。
我认为我需要这个测试,只是因为 JS 团队可能会将这种特殊情况下的
TypeError
更改为 MissingMethodError
之类的东西,但我会违反红>绿>重构原则。我该如何解决这种情况?
这种情况可能会发生,但最好避免。在这种情况下,您可以通过以不同的顺序编写测试来避免这种情况。
1) foo 存在;
红色是因为 foo 当然不存在。写一个空的 foo();现在它是绿色的。
2) 如果参数不是字符串,则 foo 会抛出 TypeError。
红色是因为 foo 从不抛出 TypeError (或其他任何错误)。让 foo 无条件抛出 TypeError;现在所有测试都是绿色的。
3) foo 去掉 a。
红色,因为没有。现在实施;现在你所有的测试都通过了,所有的测试都开始是红色的。
这似乎是一种人为的方法,当然确实如此,并且提前知道如何编写测试以遵守红绿重构并不容易。但你做得越多,它就会变得越容易。
红绿重构确实很重要,值得尝试遵循,因为如果测试一开始是绿色的,那么它可能不会对被测系统进行任何有意义的测试。有时,就像这个例子一样,你会遇到它;您可以调整被测系统以强制显示红色,但也可以尝试从中学习(正如您通过提出这个问题所做的那样),以便下次会更好。
您可以测试您的 TypeError 是否具有正确的消息。目前,这可能不是您所期望的。
最终,您应该问自己是否值得拥有自定义错误类型。使用函数时更容易测试并更容易采取行动。
这是旧的,但我的 5 美分:你不应该测试函数的存在。您应该测试需求。并且函数的存在无疑是一个要求。