5

So, I'm using mocha with chai to do my front-end testing, but I'm starting to incorporate sinon and really liking it. Except that testing throwing errors isn't working quite how the sinon docs seem to indicate.

Basically, I've got this method:

create: function(bitString, collectionType) {
    var collection;

    switch(collectionType) {
        case 'minutesOfHour':
            collection = this.createMinutesOfHour(bitString);
            break;

        case 'hoursOfDay':
            collection = this.createHoursOfDay(bitString);
            break;

        case 'daysOfWeek':
            collection = this.createDaysOfWeek(bitString);
            break;

        case 'daysOfMonth':
            collection = this.createDaysOfMonth(bitString);
            break;

        case 'monthsOfYear':
            collection = this.createMonthsOfYear(bitString);
            break;

        default:
            throw new Error('unsupported collection type ' + collectionType);
    }

    return collection;
},

and I'm testing it with this expectation:

it('throws error if missing second arguement', function() {
    sinon.spy(factory, 'create');

    factory.create();

    expect(factory.create).to.have.thrown();

    factory.create.restore();
});

however, the error, which I'm try to test for, also seems to halt the execution of the test

error message

I'd thought sinon.spy would include some try / catch logic internally, spy.throw doesn't seem as useful without it.

http://sinonjs.org/docs/#spies

Am I doing something wrong??

noTxt
  • 65
  • 1
  • 7

3 Answers3

4

I think one thing you could try is asserting against a spy object instead of the method, assign it to a variable. Not really knowing how sinon deals with all this exception magic...I think it might just work as you had expected.

it('throws error if missing second argument', function() {
  var spy = sinon.spy(factory, 'create');

  factory.create();

  expect(spy).to.have.thrown();

  factory.create.restore();
});

If that still doesn't work I think you could also do this test with standard chai if need be, leaving sinon out of the equation and actually gaining the check that the error has the correct message.

it('throws error if missing second argument', function() {
  expect(function() {
    factory.create();
  }).to.throw(/unsupported collection type/);
});

Or more concisely:

it('throws error if missing second argument', function() {
  expect(factory.create).to.throw(/unsupported collection type/);
});
nackjicholson
  • 4,557
  • 4
  • 37
  • 35
  • ( gr ... limit on editing comment ) yeah, I looked at the sinon source and sinon catches the error, then throws it again. But I think I can just use mocha's .throw() for this -- expect(factory.create).to.throw(); -- and where you want the additional spy info you could wrap the method before that assertion. – noTxt Oct 07 '13 at 18:25
0

In your expectation, you mixed chai and sinon syntax. Try

expect(factory.create.threw()).to.be.ok();
Adrian Heine
  • 4,051
  • 2
  • 30
  • 43
-1

Sometimes you'd like to check that errors were thrown on a function that you're not directly testing, i.e. the error method of an ajax call.

This approach worked swell for me:

errorStub = sinon.stub(jQuery, "ajax").yieldsTo("error");

try {
  triggerError();  // triggers ajax call which yields to an error
}

expect(errorStub.threw()).to.be.true
FreePender
  • 4,770
  • 2
  • 18
  • 15