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

12,540

Solution 1

waitsFor() will wait for a specified latch callback to return true (it will try many time every few ms). It will also raise an exception if the specified timeout (5000ms in this case) is exceeded.

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()

Solution 2

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. Otherwise it fails.

Supposing the thing you need to wait for is that r[0] is defined at all, it could be:

waitsFor(
    function() { return r[0]; },
    'the data should be already set',
    5000);
Share:
12,540
hbrls
Author by

hbrls

web/mobile, front/back, js/node/python

Updated on July 24, 2022

Comments

  • hbrls
    hbrls almost 2 years

    I'm using a function to fetch data from webapi. Basicly using $.ajax.

    I'm now testing it with waits() like this:

    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. 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. 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. The time of running the whole suite is too long to accept.

    Is there some best practice of doing there kind of things?

    PS: I know that unit test should not be applied to some function that relies on webapi or database. But I'm working with a single-page-js-heavy-webapp. The data fetching process is as important as how I will consume them with js models.

  • hbrls
    hbrls over 11 years
    When will the "failure message" be shown? The timeout prints the its own error message.
  • istepaniuk
    istepaniuk over 11 years
    If you don't specify a failure message it will show a default timeout message. If you require a custom message you can use waitsFor(function() {return fetchDone;}, "Timed out while waiting for fetch to be done, etc, etc.", 5000);
  • Gurpreet
    Gurpreet almost 10 years
    waitsFor isn't available in jasmine2.
  • trysis
    trysis about 9 years
    @Gurpreet nor is waits.
  • Emna Ayadi
    Emna Ayadi about 8 years
    What if i have a problem when clicking into the login button, no action is executed can i make a specefic wait for jasmine framework, because right now no thing happens even the onclick effect isn't displayed?