ProgramGuru

Integration Testing

Integration Testing — why it matters

Integration tests exercise the boundary between components, such as a service and repository or a request handler and persistence layer. They can reveal wiring and data-shape mistakes missed by isolated unit tests. Use predictable test data and clean up state so tests remain independent.

What you’ll learn

  • Explain integration testing and the problem it solves.
  • Identify the relevant compile-time checks and runtime responsibilities.
  • Run the example, predict its output, and try a realistic modification.

Understand the mechanism

The example crosses a service-style storage interface with an actual in-memory implementation. A real integration test should also exercise the concrete database or HTTP adapter used in production.

Testing an in-memory repository alone does not prove a SQL transaction, migration, or network integration behaves correctly.

Follow the concept flow

Integration Testing — concept flowComponent API → Repository implementation → Verify round tripIntegration Testing1Component API2Repository implementation3Verify round tripTests exercise behavior, while types check static contracts.
Follow the responsibilities from input to checked result.

Run the primary TypeScript example

Save as integration-testing.ts. The following program passed strict TypeScript compilation, and the displayed output was captured by executing its emitted JavaScript with Node.js 22.16.0.

TypeScript source

type Repository = { save(value: string): void; load(): string[] };
class MemoryRepository implements Repository {
  private values: string[] = [];
  save(value: string): void { this.values.push(value); }
  load(): string[] { return [...this.values]; }
}
const repo = new MemoryRepository();
repo.save("draft");
console.log(repo.load().join(","));

Verified output

draft

Compile: npx tsc --strict --target es2022 --module commonjs integration-testing.ts; run: node integration-testing.js. For Node.js API examples, install @types/node first. For browser projects, use the browser-specific instructions below.

The example demonstrates the code-level behavior; the related configuration or test commands are shown separately when needed.

Trace the result

The example crosses a service-style storage interface with an actual in-memory implementation. A real integration test should also exercise the concrete database or HTTP adapter used in production.

Predict what changes if you alter one input. Then run the code to compare your reasoning with the real output.

Common mistake and correction

Testing an in-memory repository alone does not prove a SQL transaction, migration, or network integration behaves correctly.

Identify whether the failure is a type-checking issue, a configuration issue, or a runtime behavior issue before choosing a fix.

Practice the concept

Replace the memory repository with a temporary file repository and assert that data survives reconstructing the repository.

Write down your expected result first. For configuration examples, compare compiler output and diagnostics; for test examples, make the assertion fail deliberately to verify that the tool reports it.

Check your understanding

Which statement makes a trustworthy TypeScript testing practice?
Choose one answer. You can try again.

Answer and explanation

A test must exercise behavior and assert an expected outcome; compiler checks and test results provide different evidence.

The example crosses a service-style storage interface with an actual in-memory implementation. A real integration test should also exercise the concrete database or HTTP adapter used in production.

What to remember

Integration tests exercise the boundary between components, such as a service and repository or a request handler and persistence layer.

Run the primary example, then complete the practice task or environment-specific lab.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Test Coverage →