Integration Testing
In this page:
What Integration Tests Verify
Integration tests verify that multiple typed units — a service, a data layer, an API client — work correctly together, catching mismatches at their boundaries that isolated unit tests (which mock those boundaries away) can't see.
Example: What Integration Tests Verify
interface Repo { save(name: string): void; }
class Service {
constructor(private repo: Repo) {}
register(name: string) { this.repo.save(name); }
}
const repo: Repo = { save: (name) => console.log("Saved:", name) };
new Service(repo).register("Ravi");
Testing API Integration
Testing API integration means calling a real or realistically-typed HTTP client against a test server, verifying the response actually matches the TypeScript interface your code expects it to have.
Example: Testing API Integration
interface User { name: string; }
async function getUser(): Promise<User> {
const response = await fetch("data.php");
return response.json();
}
getUser().then((u) => console.log(u.name));
Database Integration
Database integration tests run against a real (often in-memory or containerized) database, confirming that your typed query results actually match the shapes your ORM or query layer declares them to be.
Example: Database Integration
interface Row { id: number; name: string; }
class InMemoryDb {
private rows: Row[] = [];
insert(row: Row) { this.rows.push(row); }
find(id: number) { return this.rows.find((r) => r.id === id); }
}
const db = new InMemoryDb();
db.insert({ id: 1, name: "Ravi" });
console.log(db.find(1));
Testing Complete Workflows
Testing a complete workflow — like "create user, then log in, then fetch profile" — exercises several typed modules in sequence, catching integration bugs that only appear when real data flows between them.
Example: Testing Complete Workflows
interface User { id: number; name: string; }
class UserFlow {
private users: User[] = [];
create(name: string): User {
const user = { id: this.users.length + 1, name };
this.users.push(user);
return user;
}
login(id: number) { return this.users.find((u) => u.id === id); }
}
const flow = new UserFlow();
const created = flow.create("Ravi");
console.log(flow.login(created.id));
Integration Test Isolation
Isolating integration tests from each other (fresh database state, no shared mutable fixtures) prevents one test's typed side effects from leaking into and breaking an unrelated test that runs after it.
Example: Integration Test Isolation
class TestDatabase {
private rows: string[] = [];
reset() { this.rows = []; }
insert(row: string) { this.rows.push(row); }
}
const db = new TestDatabase();
db.insert("test-data");
db.reset();
console.log(db);
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: