Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Failing test displays "Error: timeout of 2000ms exceeded" when using Sinon-Chai

Failing test displays "Error: timeout of 2000ms exceeded" when using Sinon-Chai

Problem

I have the following route (express) for which I'm writing an integration test.

Here's the code:

var q = require("q"),
    request = require("request");

/*
    Example of service wrapper that makes HTTP request.
*/
function getProducts() {

    var deferred = q.defer();

    request.get({uri : "http://localhost/some-service" }, function (e, r, body) {
        deferred.resolve(JSON.parse(body));
    });

    return deferred.promise;
}

/*
    The route
*/
exports.getProducts = function (request, response) {
    getProducts()
        .then(function (data) {
            response.write(JSON.stringify(data));
            response.end();
        });
};

I want to test that all the components work together but with a fake HTTP response, so I am creating a stub for the request/http interactions.

I am using Chai, Sinon and Sinon-Chai and Mocha as the test runner.

Here's the test code:

var chai = require("chai"),
    should = chai.should(),
    sinon = require("sinon"),
    sinonChai = require("sinon-chai"),
    route = require("../routes"),
    request = require("request");

chai.use(sinonChai);

describe("product service", function () {
    before(function(done){
        sinon
        .stub(request, "get")
        // change the text of product name to cause test failure.
        .yields(null, null, JSON.stringify({ products: [{ name : "product name" }] }));
        done();
    });

    after(function(done){
        request.get.restore();
        done();
    });

    it("should call product route and return expected resonse", function (done) {

        var writeSpy = {},
            response = {
            write : function () { 
                writeSpy.should.have.been.calledWith("{\"products\":[{\"name\":\"product name\"}]}");
                done();
            }
        };

        writeSpy = sinon.spy(response, "write");

        route.getProducts(null, response);
    });
}); 

If the argument written to the response (response.write) matches the test passes ok. The issue is that when the test fails the failure message is:

"Error: timeout of 2000ms exceeded"

I've referenced this answer, however it doesn't resolve the problem.

How can I get this code to display the correct test name and the reason for failure?

NB A secondary question may be, could the way the response object is being asserted be improved upon?

Problem courtesy of: Bradley Braithwaite

Solution

The problem looks like an exception is getting swallowed somewhere. The first thing that comes to my mind is adding done at the end of your promise chain:

exports.getProducts = function (request, response) {
    getProducts()
        .then(function (data) {
            response.write(JSON.stringify(data));
            response.end();
        })
        .done(); /// 

It is typically the case when working with promises that you want to end your chain by calling a method like this. Some implementations call it done, some call it end.

How can I get this code to display the correct test name and the reason for failure?

If Mocha never sees the exception, there is nothing it can do to give you a nice error message. One way to diagnose a possible swallowed exception is to add a try... catch block around the offending code and dump something to the console.

Solution courtesy of: Louis

Discussion

View additional discussion.



This post first appeared on Node.js Recipes, please read the originial post: here

Share the post

Failing test displays "Error: timeout of 2000ms exceeded" when using Sinon-Chai

×

Subscribe to Node.js Recipes

Get updates delivered right to your inbox!

Thank you for your subscription

×