DevPath · Learn to code ESPTEN

Testing the complete application

Unit and integration: doubles and assertions

Isolate with test doubles

To test a unit without its real dependencies (network, DB, clock, payments) we use test doubles:

In practice the language is loose: many people call any double a "mock". What matters is the intent: stub = control inputs, spy/mock = verify outputs/interactions.

Dependency injection

To be able to replace a dependency with a double, the function must not create it internally, it must receive it. That is dependency injection:

// Hard to test: the dependency is "welded in".
function register(email) { sendRealEmail(email); }

// Easy to test: we inject the collaborator.
function register(email, sendEmail) { sendEmail(email); }
// In the test we pass a spy and verify it was called.

Test pure functions and endpoints

// Conceptual (supertest doesn't run in this sandbox):
await request(app).get("/users/1").expect(200);

In these exercises we simulate that request/response with crearReq() and crearRes(), and assert on res.statusCode and res.body.

Assertions (expect)

An assertion declares what must hold; if it doesn't, it throws and the test fails. The expect(actual).toBe(expected) API is just sugar over an if + throw.

Coverage and its limits

Coverage measures what percentage of lines/branches the suite executed. Useful for finding untested areas, but it doesn't measure quality: you can have 100% coverage and zero useful assertions. High coverage ≠ correct code.

Examples

A hand-made spy

function createSpy() {
  const spy = (...args) => { spy.calls.push(args); };
  spy.calls = [];
  return spy;
}
const send = createSpy();
function register(email, sendEmail) { sendEmail(email); }
register("ana@x.com", send);
console.log(send.calls.length === 1);       // true
console.log(send.calls[0][0] === "ana@x.com"); // true
Put this into practice

DevPath is a hands-on course: you read the theory here; in the app you put it into practice with exercises that really run, offline.

Start free in the app →
← The testing pyramidE2E: the user in a real browser →