Search code examples
javascriptsinonsinon-chai

testing promised service with Chai and Sinon


I'm stuck with testing promies in Chai and Sinon. Generally I got service with is wrapper for xhr request and it returns promises. I tried to test it like that:

beforeEach(function() {
    server = sinon.fakeServer.create();
});

afterEach(function() {
    server.restore();
});

describe('task name', function() {
    it('should respond with promise error callback', function(done) {

        var spy1 = sinon.spy();
        var spy2 = sinon.spy();

        service.get('/someBadUrl').then(spy1, spy2);

        server.respond();
        done();

        expect(spy2.calledOnce).to.be.true;
        expect(sp2.args[0][1].response.to.equal({status: 404, text: 'Not Found'});
    });
});

My notes about this:

// spy2 is called after expect finish assertion
// tried with var timer = sinon.useFakeTimers() and timer.tick(510); with no results
// tried with chai-as-promised - don’t know how use it :-(
// cannot install sinon-as-promised only selected npm modules available in my environment

Any any ideas how fix this code/ test this service module?


Solution

  • There's various challenges here:

    • if service.get() is asynchronous, you need to wait for its completion before checking your assertions;
    • since the (proposed) solution checks the assertions in a promise handler, you have to be careful with exceptions. Instead of using done(), I would opt for using Mocha's (which I assume you're using) built-in promise support.

    Try this:

    it('should respond with promise error callback', function() {
      var spy1 = sinon.spy();
      var spy2 = sinon.spy();
    
      // Insert the spies as resolve/reject handlers for the `.get()` call,
      // and add another .then() to wait for full completion.
      var result = service.get('/someBadUrl').then(spy1, spy2).then(function() {
        expect(spy2.calledOnce).to.be.true;
        expect(spy2.args[0][1].response.to.equal({status: 404, text: 'Not Found'}));
      });
    
      // Make the server respond.
      server.respond();
    
      // Return the result promise.
      return result;
    });