【问题标题】:Angular + Karma: Testing async functionsAngular + Karma:测试异步函数
【发布时间】:2014-01-15 19:52:14
【问题描述】:

我有一个 Angular 服务,它执行一些异步操作(基于计时器)。您可以使用计时器做的一件事是定义一个“处理程序”,在计时器到期时触发(如本伪代码中所示):

flag = false;
timer = new Timer(1000); // ms
timer.handler = function () { flag = true };

在这种简单的情况下,计时器会在 1 秒后将 flag 设置为 true。如何使用 Angular/Karma/Jasmine 进行单元测试?

通过阅读文档,我预计这会起作用:

... 
flag = false;
timer = new Timer(1000);
timer.handler = function () { flag = true };
expect(flag).toBe(false);
sleep(2)
expect(flag).toBe(true);
...

该测试决定失败,而不是道德上的正直:

ReferenceError: Can't find variable: sleep

经过一番阅读,显然我不能将 angular-scenario 与 Jasmine 一起使用。好的,我对此很满意。

更新根据 cmets,我测试了我的“工作”settimeout 方法。它永远不会被调用。

所以这行得通:

... 
flag = false;
timer = new Timer(1000);
timer.handler = function () { flag = true };
expect(flag).toBe(false);
setTimeout(function () { expect(flag).toBe(true) }, 2000);
...

但是感觉有点怪。

问题:有更好的方法吗?

有趣的琐事:是的,我知道 $timeout。我有很好的理由(TM)做我在代码矿深处所做的事情,远离白天=)

【问题讨论】:

  • 为什么标准超时感觉怪怪的?
  • 如果你使用 $timeout 你可以调用 $timeout.flush();有了这个,您可以测试前定时器条件和后定时器条件。但你不想要它:)
  • @rdodev: 嗯,我不知道这是否是以前感觉怪异的原因,但我刚刚测试过,超时内的 expect() 实际上并没有被调用(我设置了时间到 10 秒并重新运行测试,但它几乎立即完成)。
  • @Michael:我的计时器有一个等效于 flush() 的方法,但这不是我想要测试的。
  • 在你上一个代码 sn-p 中,Timer() 什么时候被触发?在实例化时?

标签: unit-testing angularjs asynchronous jasmine karma-runner


【解决方案1】:

Jasmine 有一种方法可以使用 waits() 或 waitsFor() 和 runs() 进行异步测试。看here

代码类似于:

... 
flag = false;
timer = new Timer(1000);
timer.handler = function () { flag = true };
expect(flag).toBe(false);
waitsFor( function() {
  return flag;
}, "timer ran");
runs( function() {
  expect(flag).toBe(true);
});
...

来自 OP 的说明

这是正确的解决方案,因此我将其标记为已接受。我实际上最终基于这个解决方案实现了一个类似睡眠的方法,并想分享它以防它对其他人有帮助。

在测试文件中:

function loiter(ms) {
  var loiter = true;
  setTimeout(function () {loiter = false}, ms);
  waitsFor( function () {return !loiter}, "Loitered too long", ms + 50); 
}

it("should ...", function () {
  flag = false;
  timer = new Timer(1000);
  timer.handler = function () {flag = true};
  setTimeout(function () {expect(flag).toBe(true)}), 1100);

  loiter(1200);
})

我希望这是有用的!我将把它作为练习留给读者了解我为什么这样做=)

【讨论】:

  • 这是正确的答案。迈克尔在上面的 cmets 中首先回答,但如果他没有尽快提供答案,我会接受你的正确答案。谢谢=)
  • “我将把它作为练习留给读者,让他们弄清楚我为什么这样做 =)”如果你能完成解释就好了。
  • setTimeout(function () {expect(flag).toBe(true)}), 1100); 应该是 setTimeout(function () {expect(flag).toBe(true)}, 1100); - 效果很好! :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-24
  • 2014-02-08
  • 2015-04-25
  • 2018-01-25
  • 1970-01-01
相关资源
最近更新 更多