简体   繁体   English

如何使用jasmine来测试需要很长时间才能响应的异步函数?

[英]How to use jasmine to test an async function that takes a long time to respond?

I'm using a function to fetch data from webapi. 我正在使用一个函数从webapi获取数据。 Basicly using $.ajax . 基本上使用$.ajax

I'm now testing it with waits() like this: 我现在用waits()测试它,如下所示:

describe('xxxxxxxxxxxxxxxxxxxxx', function () {
  var r;
  it('fetchFilter', function () {
    runs(function () {
      model.fetch(opts)
      .done(function(data) {
        r = data;
      });
    });

    waits(2000);

    runs(function () {
      expect(r[0].gender).toBeDefined();
    });
  });
});

The problem is: 问题是:

  1. It's not guaranteed that waits(2000) will do the job well. 不能保证waits(2000)能很好地完成工作。 Due to various reasons(network connections, algorithm efficiency of the api it self, etc.), I may have to waits(5000) or more, or for some models waits(500) is enough. 由于各种原因(网络连接,自身的算法效率等),我可能必须waits(5000)或更多,或者对于某些模型waits(500)就足够了。 And the most annoying thing is that it's all out of control. 最令人讨厌的是它完全失控。
  2. A lot of waits() makes the test-specs-runs waste a lot of time waiting. 很多waits()使测试规范 - 运行浪费了大量的时间等待。 The time of running the whole suite is too long to accept. 运行整个套件的时间太长,无法接受。

Is there some best practice of doing there kind of things? 有没有best practice做那种事情?

PS: I know that unit test should not be applied to some function that relies on webapi or database. PS:我知道单元测试不应该应用于某些依赖webapi或数据库的函数。 But I'm working with a single-page-js-heavy-webapp. 但我正在使用单页js-heavy-webapp。 The data fetching process is as important as how I will consume them with js models. 数据获取过程与我如何使用js模型一样重要。

waitsFor() will wait for a specified latch callback to return true (it will try many time every few ms). waitsFor()将等待指定的latch回调返回true (它将每隔几毫秒尝试很多次)。 It will also raise an exception if the specified timeout (5000ms in this case) is exceeded. 如果超过指定的超时(在这种情况下为5000ms),它也会引发异常。

describe('xxxxxxxxxxxxxxxxxxxxx', function () {
  var r, fetchDone;

  it('fetchFilter', function () {

    runs(function () {
      model.fetch(opts).done(function(data) {
        r = data;
        fetchDone = true;
      });
    });

    waitsFor(function() { 
      return fetchDone; 
    }, 5000); 

    runs(function () {
      expect(r[0].gender).toBeDefined();
    });

  });
});

Check the Jasmine docs for more info on waitsFor() and runs() 有关waitsFor()runs()更多信息,请查看Jasmine文档

The following solution allows you to wait no more than really necessary but still you have to define max timeout you suppose to be enough. 以下解决方案允许您等待不超过真正必要但仍然必须定义您认为足够的最大超时。 The waitsFor takes the function and waits until it returns true or the timeout passed as the last argument expired. waitsFor接受该函数并等待它返回true或者在最后一个参数到期时传递超时。 Otherwise it fails. 否则它会失败。

Supposing the thing you need to wait for is that r[0] is defined at all, it could be: 假设你需要等待的是r[0]被定义,它可能是:

waitsFor(
    function() { return r[0]; },
    'the data should be already set',
    5000);

As per jasmine 2.5 , you can pass an extra paramater for it("scenario", callback, timeout) 根据jasmine 2.5 ,你可以为it("scenario", callback, timeout)传递一个额外的参数it("scenario", callback, timeout)

describe('xxxxxxxxxxxxxxxxxxxxx', function (done) {
  var r, fetchDone;

  it('fetchFilter', function () {

    runs(function () {
      model.fetch(opts).done(function(data) {
        r = data;
        fetchDone = true;
      });
    });

    setTimeout(function() {
        done();
    }, 9000); 

    runs(function () {
      expect(r[0].gender).toBeDefined();
    });

  });
},10000);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM