Chai: Is there a way to show a custom error with expect syntax?

Created on 29 Jun 2012  路  15Comments  路  Source: chaijs/chai

When you use expect, errors are not always easy to interpret, especially if you have several different expects that compare similar values, e.g.:

expect(a).to.be.true;
expect(b).to.be.true;

Now, if a or b is false, the error message shown is:
expected false to be true

with no way to determine which of the expects caused the error.

It would be nice to be able to add a custom error message, although I'm not sure about a workable syntax. Maybe this could work:

expect(a).to.be.true.else.showMessage('expected a to be true, but it was false');
expect(b).to.be.true.else.showMessage('expected b to be true, but it was false');

So now if a is false, the error shown will be:
expected a to be true, but it was false.

This might be solvable by creating a plugin, but I've not really looked into that.

Most helpful comment

Oh, whoops. Sorry about that...

The a === true assertion takes place as soon as it gets to .true part of the chain so the message has to come before.

It looks like we took the long way around. An undocumented usage of a expect is as following...

expect(a, 'a is true').to.be.true;

That will yield the exact same results. Can we blame the fact I had yet to have my morning coffee and forgot I added support for custom messages on expect 6 months ago, plz :P

Anyway, if it was me... this is how i would do it:

expect(a, 'topic [a]').to.be.true;

I think you will find that as the most readable for both composition and when errors are thrown.

All 15 comments

Ah yes, a little bit of plugin code would work here...

chai.use(function (_chai, _) {
  _chai.Assertion.addMethod('withMessage', function (msg) {
    _.flag(this, 'message', msg);
  });
});

The message flag is a reserved one in Chai. It is prepending to the error message. So, using the above bit would give you this...

expect(a).to.be.true.withMessage('a is true');

Would give you this error message:

a is true: expected false to be true

For more on how to use flags, check out the Core Plugin Techniques section on flags.

It doesn't seem to work at the end. If I do it like you wrote, it doesn't work, but if I do

expect(a).withMessage('a is true').to.be.true;

it works, but it makes it less readable.

Oh, whoops. Sorry about that...

The a === true assertion takes place as soon as it gets to .true part of the chain so the message has to come before.

It looks like we took the long way around. An undocumented usage of a expect is as following...

expect(a, 'a is true').to.be.true;

That will yield the exact same results. Can we blame the fact I had yet to have my morning coffee and forgot I added support for custom messages on expect 6 months ago, plz :P

Anyway, if it was me... this is how i would do it:

expect(a, 'topic [a]').to.be.true;

I think you will find that as the most readable for both composition and when errors are thrown.

Note to self: document this!

excellent, thanks for the quick reply, and I will forget your earlier mistake ;-).

Thank you kindly!

Leaving this open for the time being as a reminder.

Ok, this has been added to the Guide section about expect. Closing.

And one more thing, a simple alternative is to use showStack set to true. http://chaijs.com/guide/styles/#configure

@logicalparadox I think you meant includeStack

chai.config.includeStack = true;

This is great but how to you stop the default error message displaying when add a custom message?

@snoblenet were you able to strip out the default error message?

@santiagodoldan no sorry

@logicalparadox hey there Jake, would you mind updating the guide for expect to also mention that you can pass in the message in the beginning (in expect) and in the end (in asserions; for assertions which are methods). For example:

expect(actual, 'message').to.include(expected);
expect(actual).to.include(expected, 'message');
expect(actual, 'message').to.be.true;

Though this is closed, this link to the chai documentation goes over creating new assertions that can have custom messages and overwrite the AssertionError messages: https://www.chaijs.com/guide/plugins/#composing-an-assertion

@snoblenet this may help you if you still are looking for a good solution

Is there any way to get this plugin working if I use _should_ this way?

const chai = require('chai')
const should = chai.should()

[...]
should.withMessage('alternative message').not.exist(foo.bar)
[...]

This throws a TypeError

     TypeError: should.withMessage is not a function

UPDATE:
Thanks to @dheerajbhaskar I got it working like this:

const chai = require('chai')
const should = chai.should()

[...]
should.not.exist(foo.bar, 'alternative message')
[...]

But it's less self-explanatory IMHO so I would prefer the withMessage version above. Any ideas?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AnAppAMonth picture AnAppAMonth  路  3Comments

jockster picture jockster  路  4Comments

meeber picture meeber  路  4Comments

huaguzheng picture huaguzheng  路  3Comments

basherr picture basherr  路  4Comments