← Back to TypeScript Course | Chapter 24: Testing TypeScript | Lesson 6 of 6

Integration Testing

Integration tests verify that multiple parts of an application work together. They usually test realistic flows across services, data access, HTTP boundaries, or other connected components instead of testing one function in isolation.

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

typescript
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

typescript
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

typescript
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

typescript
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

typescript
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:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.