What is the difference between “assert”, “expect”, and “should” in Chai?

Javascriptmocha.jsChai

Javascript Problem Overview


What is the difference between assert, expect, and should? When to use what?

assert.equal(3, '3', '== coerces values to strings');
    
var foo = 'bar';
    
expect(foo).to.equal('bar');
    
foo.should.equal('bar');

Javascript Solutions


Solution 1 - Javascript

The differences are documented there.

The three interfaces present different styles of performing assertions. Ultimately, they perform the same task. Some users prefer one style over the other. This being said, there are also a couple technical considerations worth highlighting:

  1. The assert and expect interfaces do not modify Object.prototype, whereas should does. So they are a better choice in an environment where you cannot or do not want to change Object.prototype.

  2. The assert and expect interfaces support custom messages just about everywhere. For instance:

     assert.isTrue(foo, "foo should be true");
     expect(foo, "foo should be true").to.be.true;
    

The message "foo should be true" will be output together with the failed assertion if the assertion fails. You don't get the opportunity to set a custom message with the should interface.

(Historical note: for a long time this answer stated that to get a custom message with expect, you'd have to use a workaround. Aurélien Ribon informed me that passing a message to expect as a second parameter works. Consequently, there is no need for a workaround. I've not been able to find which version of Mocha started providing support for this message, nor have I been able to find which version of the documentation documented it for the first time.)

Note that assert.isTrue(foo), expect(foo).to.be.true and foo.should.be.true all output the following if you do not use a custom message, and foo === 1:

    AssertionError: expected 1 to be true

So while the expect and should interface are nicer to read, it is not like one interface is more naturally informative than the other when an assertion fails. This message, which is identical for all three interfaces, does not tell you what exactly you were testing, only that the value you got was 1 but you wanted true. If you want to know what you were testing, you need to add a message.

Solution 2 - Javascript

I hope this simple examples makes their differences clear

Assert

var assert = require('chai').assert
const foo = 'bar'
const beverages = { tea: [ 'chai', 'matcha', 'oolong' ] };

assert.typeOf(foo, 'string'); // without optional message
assert.typeOf(foo, 'string', 'foo is a string'); // with optional message
assert.equal(foo, 'bar', 'foo equal `bar`');
assert.lengthOf(foo, 3, 'foo`s value has a length of 3');
assert.lengthOf(beverages.tea, 3, 'beverages has 3 types of tea');

In all cases, the assert style allows you to include an optional message as the last parameter in the assert statement. These will be included in the error messages should your assertion not pass.

Note expect and should uses chainable language to construct assertions, but they differ in the way an assertion is initially constructed. In the case of should, there are also some caveats and additional tools to overcome the caveats.

Expect

var expect = require('chai').expect
const foo = 'bar'
const beverages = { tea: [ 'chai', 'matcha', 'oolong' ] };
expect(foo).to.be.a('string');
expect(foo).to.equal('bar');
expect(foo).to.have.lengthOf(3);
expect(beverages).to.have.property('tea').with.lengthOf(3);

expect allows you to include arbitrary messages to prepend to any failed assertions that might occur.

var answer = 43;

// AssertionError: expected 43 to equal 42.
expect(answer).to.equal(42);

// AssertionError: topic [answer]: expected 43 to equal 42.
expect(answer, 'topic [answer]').to.equal(42);

This comes in handy when being used with non-descript topics such as booleans or numbers.

Should

The should style allows for the same chainable assertions as the expect interface, however it extends each object with a should property to start your chain. This style has some issues when used with Internet Explorer, so be aware of browser compatibility.

var should = require('chai').should() //actually call the function
const foo = 'bar'
const beverages = { tea: [ 'chai', 'matcha', 'oolong' ] };

foo.should.be.a('string');
foo.should.equal('bar');
foo.should.have.lengthOf(3);
beverages.should.have.property('tea').with.lengthOf(3);

Differences between expect and should

First of all, notice that the expect require is just a reference to the expect function, whereas with the should require, the function is being executed.

var chai = require('chai')
const expect = chai.expect
const should = chai.should();

The expect interface provides a function as a starting point for chaining your language assertions. It works on node.js and in all browsers.

The should interface extends Object.prototype to provide a single getter as the starting point for your language assertions. It works on node.js and in all modern browsers except Internet Explorer.

Solution 3 - Javascript

Correct me if I'm wrong, but there is also a huge difference between an assert and an expect in terms of code running behavior. Assert is supposed to stop the program on error. Expect is not.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionManuView Question on Stackoverflow
Solution 1 - JavascriptLouisView Answer on Stackoverflow
Solution 2 - JavascriptAdépòjù OlúwáségunView Answer on Stackoverflow
Solution 3 - JavascriptmatreuraiView Answer on Stackoverflow