当带有 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() 函数传递另一个函数,然后它可以 wraptry...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 中看到它。