docs/src/content/docs/explainers/spies.mdx
Mocha does not come equipped with spies, though libraries like Sinon provide this behaviour if desired. The following is an example of Mocha utilizing Sinon to test an EventEmitter:
import sinon from "sinon";
import { EventEmitter } from "node:events";
describe("EventEmitter", function () {
describe("#emit()", function () {
it("should invoke the callback", function () {
const spy = sinon.spy(),
emitter = new EventEmitter();
emitter.on("foo", spy);
emitter.emit("foo");
sinon.assert.calledOnce(spy);
});
it("should pass arguments to the callbacks", function () {
const spy = sinon.spy(),
emitter = new EventEmitter();
emitter.on("foo", spy);
emitter.emit("foo", "bar", "baz");
sinon.assert.calledOnce(spy);
sinon.assert.calledWith(spy, "bar", "baz");
});
});
});
The following is the same test, performed without any special spy library, utilizing the Mocha done([err]) callback as a means to assert that the callback has occurred, otherwise resulting in a timeout. Note that Mocha only allows done() to be invoked once, and will otherwise error.
import { strict as assert } from "node:assert";
import { EventEmitter } from "node:events";
describe("EventEmitter", function () {
describe("#emit()", function () {
it("should invoke the callback", function (done) {
const emitter = new EventEmitter();
emitter.on("foo", done);
emitter.emit("foo");
});
it("should pass arguments to the callbacks", function (done) {
const emitter = new EventEmitter();
emitter.on("foo", function (a, b) {
assert.equal(a, "bar");
assert.equal(b, "baz");
done();
});
emitter.emit("foo", "bar", "baz");
});
});
});