1

Here is a NodeJS module:

var plural = function(words, num) {
    if (words.length != 3) {
        throw new Error('Wrong words array');
    }
    var lastNum = num % 10;
    var second = (num / 10) % 10;
    if (second == 1)
        return words[2]
    else if (lastNum == 1)
        return words[0];
    else if (lastNum <= 4)
        return words[1];
    else
        return words[2];
};

module.exports = plural;

And here is module test:

var expect = require('chai').expect;
var plural = require('../plural')

describe('Test with wrong array', function() {

    it('Must throw Error', function() {
        expect(plural(['я','меня'])).to.throw(Error);
    });

});

I want to test exception throwing. But this is mocha's output:

 Test with wrong array
   1) Must throw Error

 1 failing

 1) Test with wrong array Must throw Error:
    Error: Wrong words array
     at plural (C:\Users\home\Google Drive\Учеба\Спецкурсы\Яндекс.Интерфейсы\TestableCode\testable-code-01\plural.js:3:9)
     at Context.<anonymous> (C:\Users\home\Google Drive\Учеба\Спецкурсы\Яндекс.Интерфейсы\TestableCode\testable-code-01\test\cat.test.js:31:10)
     at callFn (C:\Users\home\AppData\Roaming\npm\node_modules\mocha\lib\runnable.js:250:21)
     at Test.Runnable.run (C:\Users\home\AppData\Roaming\npm\node_modules\mocha\lib\runnable.js:243:7)
     at Runner.runTest (C:\Users\home\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:373:10)
     at C:\Users\home\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:451:12
     at next (C:\Users\home\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:298:14)
     at C:\Users\home\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:308:7
     at next (C:\Users\home\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:246:23)
     at Object._onImmediate (C:\Users\home\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:275:5)
     at processImmediate [as _immediateCallback] (timers.js:345:15)

So, my code throws exceptions, which is right behavior, and test should be passed. But is doesn't. What's the problem?

michaeluskov
  • 1,729
  • 7
  • 27
  • 53
  • You have to pass a function to expect() by reference - see my updated answer below and [test cases](https://github.com/chaijs/chai/blob/master/test/expect.js#L676) – netpoetica Oct 23 '14 at 17:56

3 Answers3

1

Chai's to.throw() method is shorthand for an assertThrows method which expects a couple of arguments to be passed to it. You can see an example of to.throw() here. It looks like throws() needs to be passed the constructor of the Error you will throw.

You can see the definition of AssertionError in Chai's seperate library 'assertion-error' here if you are interested in throwing a custom error message.

In your case, you should be able to pass in Error.constructor or Error I would imagine to achieve the same effect.

expect(plural(['я','меня'])).to.throw(Error);

Also, you have to pass the function to expect by reference - you are executing the function before it gets to be used as an argument to expect:

expect(function(){
   plural(['я','меня']);
}).to.throw(Error);
netpoetica
  • 3,375
  • 4
  • 27
  • 37
  • the test fails either with `expect(plural(['я','меня'])).to.throw(Error.constructor);` – michaeluskov Oct 23 '14 at 17:40
  • Essentially, the last step you need to do is find out what the constructor of your Error function is. When you call 'throw new Error()' it should just use Error as it's constructor - you aren't redefining the Error global anywhere are you? – netpoetica Oct 23 '14 at 17:51
0

Perhaps the line:

expect(plural(['я','меня'])).to.throw();

Should read

expect(plural(['я','меня'])).to.throw(Error);
Evan Shortiss
  • 1,638
  • 1
  • 10
  • 15
0

If I just replace your expect(plural... line with

expect(plural.bind(undefined, ['я','меня'])).to.throw(Error);

then it works.

As netpoetica explained, you can't just put plural(...) inside expect because then plural is called before expect executes and what expect gets is the return value of plural but because it throws an exception, expect does not get to execute. Also, what expect wants is a function that it will call to check whether or not it throws an exception. netpoetica used an anonymous function to do that. I prefer to use bind. What bind does in the code above is create a new function from plural which when called will have the value of this set to undefined and the first parameter set to ['я','меня'].

Louis
  • 146,715
  • 28
  • 274
  • 320