Matt Fenwick
Matt Fenwick

Reputation: 49095

How do I test an asynchronous callback?

I'm trying to test an ansynchronous callback by checking that it's called, say, n times in m seconds.

Here's my code so far:

test("async callback", function() {
    expect(1);
    var called = 0;

    var callback = function() {called++;};

    var model = new Model(callback);
    model.startCallbacks();

    function theTest() {         // call this a few seconds later and verify
        model.stopCallbacks();   //   that the callback has been called n times
        equal(3, called, "number of times callback was called");
    }

    setTimeout(theTest, 10000); // wait about 10 seconds until calling theTest
});

(model.startCallbacks and model.stopCallbacks are implemented with setInterval.)

This doesn't work. I think it's because execution goes off the end of the test function while callback is still being asynchronously executed.

What I want to test: that model is correctly calling callback. How do I do this?

Upvotes: 1

Views: 3885

Answers (2)

Domenic
Domenic

Reputation: 112857

// use asyncTest instead of test
asyncTest("async callback", function() {
    expect(1);
    var called = 0;

    var callback = function() {called++;};

    var model = new Model(callback);
    model.startCallbacks();

    function theTest() {         // call this a few seconds later and verify
        model.stopCallbacks();   // that the callback has been called
        equal(3, called, "number of times callback was called");

        // THIS IS KEY: it "restarts" the test runner, saying
        // "OK I'm done waiting on async stuff, continue running tests"
        start();
    }

    setTimeout(theTest, 10000); // wait about 10 seconds until calling theTest
});

Upvotes: 4

Michiel Overeem
Michiel Overeem

Reputation: 3992

You should use the start and stop functions for asynchronous testing (see the docs), example:

test("a test", function() {
  stop();
  $.getJSON("/someurl", function(result) {
    equal(result.value, "someExpectedValue");
    start();
  });
});

Your example would be:

test("async callback", function() {
    stop(1);
    var called = 0;

    var callback = function() {called++;};

    var model = new Model(callback);
    model.startCallbacks();

    function theTest() {         // call this a few seconds later and verify
        model.stopCallbacks();   //   that the callback has been called n times
        equal(3, called, "number of times callback was called");
        start();
    }

    setTimeout(theTest, 10000); // wait about 10 seconds until calling theTest
});

You can also use the shortcut asyncTest.

Upvotes: 2

Related Questions