Chai is the assertion library most commonly paired with Mocha in a Karma setup. This lesson covers karma-chai, and Chai's three distinct assertion styles.
Setting Up karma-chai
karma-chai injects Chai's global assertion interfaces into the browser page, the same way karma-jasmine injects Jasmine's. It's typically listed in frameworks alongside mocha, since Chai provides assertions but not the test runner structure itself.
expect is the most widely used style and the one most Karma+Chai projects standardize on.
should reads fluently but modifies Object.prototype, which some teams avoid for that reason.
assert most closely resembles traditional assertion libraries and Node's built-in assert module.
Pick exactly one style per project; mixing all three makes specs inconsistent to read.
Chai expect() Cheat Sheet
The most common Chai assertions in the expect style.
Assertion
Checks
expect(x).to.equal(y)
Strict equality (===)
expect(x).to.deep.equal(y)
Deep equality for objects/arrays
expect(x).to.be.true / .false
Boolean value checks
expect(x).to.be.null / .undefined
Exact null/undefined checks
expect(x).to.include(y)
Array/string contains a value
expect(x).to.have.length(n)
Array/string length
expect(fn).to.throw()
Function throws when called
expect(x).to.have.property('key')
Object has a given property
Chai's Chainable, Readable Language
Chai's defining feature is its chainable, English-like assertion syntax. Words like to, be, have, and deep exist purely for readability — they don't perform checks themselves, only the final method or property in the chain does.
Chainable language words make assertions read closer to natural English, at the cost of a steeper initial learning curve than simpler assertion styles.
Combining Chai with Sinon for Mocking
Chai itself provides no mocking. sinon-chai extends Chai with assertions specifically for Sinon spies and stubs, giving Mocha+Chai projects mocking-aware assertions similar to Jasmine's .toHaveBeenCalledWith().
npm install --save-dev sinon sinon-chai
// setup file loaded before specs
chai.use(sinonChai);
// in a spec:
const spy = sinon.spy();
doSomething(spy);
expect(spy).to.have.been.calledWith('expected-arg');
Common Mistakes
Mixing expect, should, and assert styles inconsistently across the same test suite.
Using .to.equal() for deep object comparison instead of .to.deep.equal(), causing unexpected failures.
Forgetting chai.use(sinonChai) before trying to use Sinon-specific Chai assertions.
Assuming Chai's chainable words (to, be, have) perform assertions themselves rather than just improving readability.
Key Takeaways
karma-chai injects Chai's assertion interfaces as browser globals, typically alongside Mocha.
Chai supports three styles — expect, should, and assert — pick one consistently per project.
Chai's chainable language (to, be, have, deep) improves readability without performing checks itself.
sinon-chai bridges Sinon's mocking with Chai's assertion syntax for a Jasmine-spy-like experience.
Pro Tip
If your team is deciding between Chai styles for a new suite, default to expect. It reads nearly as naturally as should without modifying built-in prototypes, and it maps most intuitively for developers coming from Jasmine or Jest.
You now understand Chai's assertion styles. Next, learn how karma-webpack bundles modules for more complex projects.