当带有 arg 的函数抛出时 QUnit 终止,除非包装在匿名函数中
QUnit terminates when function with arg throws unless wrapped in anon function
我正在使用 QUnit 测试一个函数,该函数在无效输入的情况下会抛出错误。我是能够通过将其嵌入到匿名函数中来测试该函数,但我不确定为什么这是必要的。如果我不这样做,QUnit 报告:
Died on test #4 at http://localhost:8000/qunit/throwsTest.js:1:7: sometimesThrows
值得注意的是,此消息包括 抛出的错误。
我还注意到,如果我将函数作为参数传递而不是调用它,我可以使不需要 args 的函数工作。
查看 my fiddle 观看直播。
QUnit.test("throws test", function(assert) {
function alwaysThrows() { throw "alwaysThrows"; }
function sometimesThrows(foo) {
if (foo) {
return true;
}
else {
throw "sometimesThrows";
}
}
assert.throws(alwaysThrows, "alwaysThrows throws (works)")
assert.ok(sometimesThrows(true), "sometimesThows doesn't throw (works)");
assert.throws(function() {
sometimesThrows(false);
}, "sometimesThrows throws inside anonymous function (works)");
// Where the unexpected behavior occurs.
// The error _is_ being thrown being thrown.
assert.throws(sometimesThrows(false), "sometimesThrows throws (terminates)");
});
如果将要测试的函数包装在匿名函数中是让它工作的预期方法,如果有人可以解释 为什么 ,我会发现这对开发我的直觉。
TL;DR:这正是 throws()
assertion in QUnit 的预期工作方式,以及它必须如何工作。
冗长的回复:
在您的示例中,您使用调用 sometimesThrows(false)
的 结果 来调用断言。也就是说,在上面的示例中,当您调用 QUnit 断言方法 (assert.throws()
) 时,您传入了两个值:来自 sometimesThrows()
的 return 值和一个字符串消息.
换句话说,你的例子:
assert.throws(sometimesThrows(false), "sometimesThrows throws (terminates)");
首先首先调用带有false
参数的sometimesThrows()
方法,立即执行那个方法,从而引发错误。但是那个错误去哪儿了?事实是,该错误是从您的方法 (sometimesThrows()
) 中直接抛出到 您编写的 test()
中,完全绕过了 assert.throws()
称呼。换句话说,assert.throws()
函数调用永远不会发生,因为在执行流程中调用它之前会抛出错误。
相反,我们必须向 assert.throws()
函数传递另一个函数,然后它可以 wrap 在 try...catch
块中检测是否有错误被扔了。如果您愿意,我们可以将其分离出来并实际传递一个命名函数(相对于匿名内联函数),但这实际上并没有改变任何东西:
QUnit.test("throws test", 函数(断言) {
// ..
function sometimesWrapper() {
sometimesThrows(false);
}
assert.throws(sometimesWrapper, "sometimesThrows throws (terminates)");
});
请注意,我们不调用 sometimesWrapper()
,而是将其作为参数传递给throws()
断言方法。在内部,QUnit 会将 sometimesWrapper()
的实际 调用 包装在 try...catch
块中,以便它可以确定断言是通过还是失败。如果您愿意,可以在 source code on Github 中看到它。
我正在使用 QUnit 测试一个函数,该函数在无效输入的情况下会抛出错误。我是能够通过将其嵌入到匿名函数中来测试该函数,但我不确定为什么这是必要的。如果我不这样做,QUnit 报告:
Died on test #4 at http://localhost:8000/qunit/throwsTest.js:1:7: sometimesThrows
值得注意的是,此消息包括 抛出的错误。
我还注意到,如果我将函数作为参数传递而不是调用它,我可以使不需要 args 的函数工作。
查看 my fiddle 观看直播。
QUnit.test("throws test", function(assert) {
function alwaysThrows() { throw "alwaysThrows"; }
function sometimesThrows(foo) {
if (foo) {
return true;
}
else {
throw "sometimesThrows";
}
}
assert.throws(alwaysThrows, "alwaysThrows throws (works)")
assert.ok(sometimesThrows(true), "sometimesThows doesn't throw (works)");
assert.throws(function() {
sometimesThrows(false);
}, "sometimesThrows throws inside anonymous function (works)");
// Where the unexpected behavior occurs.
// The error _is_ being thrown being thrown.
assert.throws(sometimesThrows(false), "sometimesThrows throws (terminates)");
});
如果将要测试的函数包装在匿名函数中是让它工作的预期方法,如果有人可以解释 为什么 ,我会发现这对开发我的直觉。
TL;DR:这正是 throws()
assertion in QUnit 的预期工作方式,以及它必须如何工作。
冗长的回复:
在您的示例中,您使用调用 sometimesThrows(false)
的 结果 来调用断言。也就是说,在上面的示例中,当您调用 QUnit 断言方法 (assert.throws()
) 时,您传入了两个值:来自 sometimesThrows()
的 return 值和一个字符串消息.
换句话说,你的例子:
assert.throws(sometimesThrows(false), "sometimesThrows throws (terminates)");
首先首先调用带有false
参数的sometimesThrows()
方法,立即执行那个方法,从而引发错误。但是那个错误去哪儿了?事实是,该错误是从您的方法 (sometimesThrows()
) 中直接抛出到 您编写的 test()
中,完全绕过了 assert.throws()
称呼。换句话说,assert.throws()
函数调用永远不会发生,因为在执行流程中调用它之前会抛出错误。
相反,我们必须向 assert.throws()
函数传递另一个函数,然后它可以 wrap 在 try...catch
块中检测是否有错误被扔了。如果您愿意,我们可以将其分离出来并实际传递一个命名函数(相对于匿名内联函数),但这实际上并没有改变任何东西:
QUnit.test("throws test", 函数(断言) { // ..
function sometimesWrapper() {
sometimesThrows(false);
}
assert.throws(sometimesWrapper, "sometimesThrows throws (terminates)");
});
请注意,我们不调用 sometimesWrapper()
,而是将其作为参数传递给throws()
断言方法。在内部,QUnit 会将 sometimesWrapper()
的实际 调用 包装在 try...catch
块中,以便它可以确定断言是通过还是失败。如果您愿意,可以在 source code on Github 中看到它。