javascriptunit-testingcallbackmocha.jsmocha-phantomjs

timeout of 2000ms exceeded mocha


I have two test cases i.e. it("should pass with..").. and it("should fail with..").., When I test this it gave timeout of 2000ms exceeded error.

describe("flickrphotoSearch", function () {
it("should pass with correct inputs", function (done) {
    flickrApplication.flickrPhotoSearch("hello", "flickr_user_Key", 1, handleData);
    function handleData(photoUrl, done) {
        this.setTimeout(1500);
        assert.isString(photoUrl.toString(), 'not a string');
        setTimeout(done, 1000);
    };
});
it("should fail with wrong key", function (callingDone) {
    flickrApplication.flickrPhotoSearch("hello", "wrong key", 1, handleData);
    function handleData(photoUrl, done) {
        this.setTimeout(1500);
        assert.equal(photoUrl.stat, "ok", photoUrl.message);
        setTimeout(done, 1000);
    };
});
});

for the first test I am getting timeout exceeded error, but second one is running good. Please tell me where I am wrong.


Solution

  • There are two parts to this. First, when you try to set the timeout for the test, you're not calling the setTimeout method on the right object. This is due to closure:

    describe("flickrphotoSearch", function () {
    it("should pass with correct inputs", function (done) {
        # 'this' is the mocha test here.
        flickrApplication.flickrPhotoSearch("hello", "flickr_user_Key", 1, handleData);
        function handleData(photoUrl, done) {
            this.setTimeout(1500); # What's 'this' here? The global object.
            assert.isString(photoUrl.toString(), 'not a string');
            setTimeout(done, 1000);
        };
    });
    

    When handleData is called, this is not bound to anything as the function is called on its own, not as an object method. For more information on closures and this binding see this jQuery Learning Center article. You could correct that by doing:

    flickrApplication.flickrPhotoSearch("hello", "flickr_user_Key", 1, handleData.bind(this));
    

    However, in this case you might as well move this.setTimeout(1500) outside handleData, and it'd have the same effect.

    The other part is that, if the 2000ms timeout is being exceeded, your 1500ms limit will be exceeded as well. Moreover, this is non-deterministic, as it depends on the flickr API response time.

    My advice is to mock the flickr API if this is a unit test (in contrast to integration testing).