Mocha Testing Skill
Core Patterns
Basic Test with Chai
const { expect } = require('chai');
describe('Calculator', () => {
let calc;
beforeEach(() => { calc = new Calculator(); });
it('should add two numbers', () => {
expect(calc.add(2, 3)).to.equal(5);
});
it('should throw on divide by zero', () => {
expect(() => calc.divide(10, 0)).to.throw('Division by zero');
});
});
Chai Assertions
expect(value).to.equal(5);
expect(arr).to.have.lengthOf(3);
expect(obj).to.have.property('name');
expect(str).to.include('hello');
expect(fn).to.throw(Error);
expect(arr).to.deep.equal([1, 2, 3]);
expect(obj).to.deep.include({ name: 'Alice' });
Sinon Mocking
const sinon = require('sinon');
describe('UserService', () => {
let sandbox;
beforeEach(() => { sandbox = sinon.createSandbox(); });
afterEach(() => { sandbox.restore(); });
it('fetches user from API', async () => {
const stub = sandbox.stub(api, 'get').resolves({ name: 'Alice' });
const user = await userService.getUser(1);
expect(user.name).to.equal('Alice');
expect(stub.calledOnce).to.be.true;
});
});
Async Testing
it('should fetch data', async () => {
const data = await fetchData();
expect(data).to.have.property('id');
});
it('callback style', (done) => {
fetchData((err, data) => {
expect(err).to.be.null;
done();
});
});
Anti-Patterns
| Bad |
Good |
Why |
Missing done() |
Use async/await |
Hanging tests |
| No sandbox |
sinon.createSandbox() |
Stubs leak |
Arrow in describe |
Regular function for this.timeout() |
Context |
Quick Reference
| Task |
Command |
| Run all |
npx mocha |
| Watch |
npx mocha --watch |
| Grep |
npx mocha --grep "login" |
| Timeout |
npx mocha --timeout 10000 |
| Recursive |
npx mocha --recursive |
Setup: npm install mocha chai sinon --save-dev
Deep Patterns → reference/playbook.md
| § |
Section |
Lines |
| 1 |
Production Configuration |
mocharc, NYC coverage, TypeScript |
| 2 |
Testing with Chai + Sinon |
Stubs, spies, assertions |
| 3 |
Advanced Sinon Patterns |
Fake timers, nock HTTP, sequential |
| 4 |
Async Patterns |
Promise, await, callback, events |
| 5 |
Hooks & Test Organization |
Lifecycle, nesting, grep tags |
| 6 |
Custom Reporters & Plugins |
Reporter class, root hooks |
| 7 |
Express/API Testing |
Supertest integration |
| 8 |
CI/CD Integration |
GitHub Actions, services |
| 9 |
Debugging Quick-Reference |
10 common problems |
| 10 |
Best Practices Checklist |
13 items |
1---2name: mocha-skill3description: Generates Mocha tests in JavaScript with Chai assertions and Sinon mocking. Use when user mentions "Mocha", "Chai", "sinon", "describe/it (not Jest)". Triggers on: "Mocha", "Chai", "sinon", "mocha test".4license: MIT5---6
7# Mocha Testing Skill
8
9## Core Patterns
10
11### Basic Test with Chai
12
13```javascript
14const { expect } = require('chai');
15
16describe('Calculator', () => {
17 let calc;
18 beforeEach(() => { calc = new Calculator(); });
19
20 it('should add two numbers', () => {
21 expect(calc.add(2, 3)).to.equal(5);
22 });
23
24 it('should throw on divide by zero', () => {
25 expect(() => calc.divide(10, 0)).to.throw('Division by zero');
26 });
27});
28```
29
30### Chai Assertions
31
32```javascript
33expect(value).to.equal(5);
34expect(arr).to.have.lengthOf(3);
35expect(obj).to.have.property('name');
36expect(str).to.include('hello');
37expect(fn).to.throw(Error);
38expect(arr).to.deep.equal([1, 2, 3]);
39expect(obj).to.deep.include({ name: 'Alice' });
40```
41
42### Sinon Mocking
43
44```javascript
45const sinon = require('sinon');
46
47describe('UserService', () => {
48 let sandbox;
49 beforeEach(() => { sandbox = sinon.createSandbox(); });
50 afterEach(() => { sandbox.restore(); });
51
52 it('fetches user from API', async () => {
53 const stub = sandbox.stub(api, 'get').resolves({ name: 'Alice' });
54 const user = await userService.getUser(1);
55 expect(user.name).to.equal('Alice');
56 expect(stub.calledOnce).to.be.true;
57 });
58});
59```
60
61### Async Testing
62
63```javascript
64it('should fetch data', async () => {
65 const data = await fetchData();
66 expect(data).to.have.property('id');
67});
68
69it('callback style', (done) => {
70 fetchData((err, data) => {
71 expect(err).to.be.null;
72 done();
73 });
74});
75```
76
77### Anti-Patterns
78
79| Bad | Good | Why |
80|-----|------|-----|
81| Missing `done()` | Use async/await | Hanging tests |
82| No sandbox | `sinon.createSandbox()` | Stubs leak |
83| Arrow in `describe` | Regular function for `this.timeout()` | Context |
84
85## Quick Reference
86
87| Task | Command |
88|------|---------|
89| Run all | `npx mocha` |
90| Watch | `npx mocha --watch` |
91| Grep | `npx mocha --grep "login"` |
92| Timeout | `npx mocha --timeout 10000` |
93| Recursive | `npx mocha --recursive` |
94
95## Setup: `npm install mocha chai sinon --save-dev`
96
97## Deep Patterns → `reference/playbook.md`
98
99| § | Section | Lines |
100|---|---------|-------|
101| 1 | Production Configuration | mocharc, NYC coverage, TypeScript |
102| 2 | Testing with Chai + Sinon | Stubs, spies, assertions |
103| 3 | Advanced Sinon Patterns | Fake timers, nock HTTP, sequential |
104| 4 | Async Patterns | Promise, await, callback, events |
105| 5 | Hooks & Test Organization | Lifecycle, nesting, grep tags |
106| 6 | Custom Reporters & Plugins | Reporter class, root hooks |
107| 7 | Express/API Testing | Supertest integration |
108| 8 | CI/CD Integration | GitHub Actions, services |
109| 9 | Debugging Quick-Reference | 10 common problems |
110| 10 | Best Practices Checklist | 13 items |