【问题标题】:Why is using jasmine's runs and waitFor function necessary?为什么需要使用 jasmine 的 runs 和 waitFor 功能?
【发布时间】:2014-08-28 11:18:14
【问题描述】:

我正在测试一段异步代码,如下所示:

randomService.doSomething().then(function() {
    console.log('I completed the operation!');
});

令我惊讶的是(对我来说)我发现它只有在包裹在 jasmine 的 runs 函数中时才会成功(即显示 console.log 输出),如下所示:

var isDone = false;

runs(function() {
    randomService.doSomething().then(function(data) {
        console.log('I completed the operation!');
        isDone = true;
    });
});

waitsFor(function() {
    return isDone;
}, 'Operation should be completed', 1000);

据我了解,我认为waitsFor 只是为了延迟代码,换句话说,如果我有更多代码必须延迟到异步调用完成之后,我会使用它 - 换句话说,我会以为我没有理由使用runswaitsFor,因为在这段代码之后没有任何内容,对吧?这就是我从阅读这个问题中得到的印象:What do jasmine runs and waitsFor actually do? 但显然我在某些时候把自己搞混了。

有人对此有什么想法吗?


编辑: 这是一个更详细的问题的Plunker: http://plnkr.co/edit/3qnuj5N9Thb2UdgoxYaD?p=preview

请注意第一个测试总是通过,而第二个测试却失败了。 另外,我确定我之前应该提到过这一点,但这是使用 angularJS 和 Jasmine 1.3。

【问题讨论】:

  • 如果我可以建议的话 - 现在 Mocha 已经支持原生承诺,真的没有充分的理由将 Jasmine 与承诺一起使用。
  • @Benjamin-Gruenbaum 好吧,我绝对愿意尝试新事物,我真的更愿意坚持使用 Jasmine,因为我现在正在做的项目是使用 angularJS,而且似乎Jasmine 是 Angular 的首选测试方法,但如果我错了,请纠正我。
  • 因为你使用的是 angular,所以我会坚持使用 jasmine。

标签: javascript angularjs unit-testing asynchronous jasmine


【解决方案1】:

我想我找到了问题所在。这是文章:http://blogs.lessthandot.com/index.php/webdev/uidevelopment/javascript/testing-asynchronous-javascript-w-jasmine/

基本上这是必要的,因为 Jasmine 在完成测试之前不会等待异步调用完成。根据这篇文章,如果一个调用花费的时间足够长并且之后有更多的测试,那么之前测试中异步回调中的expect 语句最终可能会在原始测试完成后完全在另一个测试中执行。

使用runswaitsFor 可以解决问题,因为它们会强制茉莉花等待waitsFor 完成,然后再进行下一个测试;然而,这是一个有争议的问题,因为显然 Jasmine 2.0 以比 1.3 更好的方式解决了异步测试,已经淘汰了 runswaitsFor

【讨论】:

  • 你去,这是有道理的。很高兴你能解决这个问题。
【解决方案2】:

这就是 Jasmine 的工作原理。您链接的问题有一个很好的解释:

本质上,runs() 和 waitFor() 函数填充一个数组 他们提供的功能。然后数组由 jamine 处理 其中函数被顺序调用。那些功能 由 runs() 注册的预计将执行实际工作,而那些 由 waitFor() 注册的预计是“闩锁”功能,并将 每 10 毫秒轮询(调用)一次,直到它们返回 true 或可选 注册的超时期限到期。如果超时期限到期 使用可选的注册错误消息报告错误; 否则,该过程将继续数组中的下一个函数。

综上所述,每个waitsFor调用都必须有一个对应的runs调用。他们一起工作。在没有任何意义之前调用 waitsFor 而没有 runs 在某处调用。


我修改后的 plunker(请参阅此答案的 cmets):http://plnkr.co/edit/9eL9d9uERre4Q17lWQmw

如您所见,我在您正在测试的超时函数中添加了$rootScope.$apply();。这使得 Promise 回调中的 console.log 运行。但是,它仅在您使用xit 忽略其他测试时才会运行,并且console.log 之后的expect 似乎不被识别为茉莉花测试(尽管它肯定必须运行,因为console.log 确实如此) .

非常奇怪 - 我真的不明白为什么会发生这种情况,但我认为这与 Jasmine 在幕后的工作方式、它如何注册测试等等有关。我现在的理解是,如果你在异步回调中有一个 expect,Jasmine 不会“识别”它作为测试套件的一部分,除非初始异步调用是在 runs 内进行的。

至于为什么会这样,我不知道。我认为不值得尝试理解 - 我只会使用 runswaitsFor 而不必担心,但这只是我。如果您感到受虐,您可以随时挖掘源代码。抱歉,我无法提供更多帮助。

【讨论】:

  • 这部分我有点理解,但我主要看不到的是为什么首先需要使用runswaitsFor。我只是不明白为什么没有它们该代码将无法工作-您能向我解释一下那部分吗?
  • 在没有它们的情况下运行代码会发生什么? waitsFor 让您以“茉莉花”方式测试未知错误和超时。通常我的waitsFor 函数除了返回一个布尔值之外什么都不做。我的承诺根据服务返回的数据是否正确设置布尔值。
  • 这很奇怪 - 如果我在不使用 runs 的情况下运行 jasmine 测试,那么我在回调函数中的任何内容都不会执行。但是,如果我在测试环境之外运行代码,它会完美运行,这也是我对 Jasmine 在这里所做的事情感到如此困惑的原因之一。
  • 哦,我明白你的意思了。控制台日志不显示?我怀疑代码正在运行,但 jasmine 没有看到控制台日志 - 因为您没有使用 runs。不是 100% 确定 为什么 这是,但我知道对 runs 的调用是一个单独的测试块。我会用runs 微笑,因为茉莉花很奇怪。顺便说一句,如果您使用的是无头浏览器,请尝试使用 chrome 并查看控制台日志是否出现。
  • 我想代码可能正在运行,但我不这么认为 - 当我尝试进行一个保证失败的测试时(即expect(true).toBe(false) 测试仍然通过,所以我认为它可能根本不会运行。我肯定在使用runs(我必须让我的代码工作)但很高兴知道为什么会出现这种情况 - 我可以不要忍受写我不完全理解的代码......
猜你喜欢
  • 2018-10-06
  • 2014-08-29
  • 2013-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-18
相关资源
最近更新 更多