Skip to content

Latest commit

 

History

History
209 lines (157 loc) · 6.57 KB

File metadata and controls

209 lines (157 loc) · 6.57 KB

Integration Testing

This directory contains cross-service integration tests that verify message contracts between FizzBuzz services using real Kafka infrastructure.

Overview

Integration tests fill the gap between unit tests (mocked dependencies) and E2E tests (full Docker Compose stack):

Layer Scope Speed Infrastructure
Unit Tests Single service Fast (~1s) Mocked
Integration Tests Message contracts Medium (~30s) Testcontainers
E2E Tests Full pipeline Slow (~5min) Docker Compose

Architecture

┌─────────────────────────────────────────────────────────────┐
│                    Integration Test Layer                    │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐     │
│  │   Producer  │───▶│  Redpanda   │───▶│  Consumer   │     │
│  │  (Test)     │    │ (Container) │    │  (Test)     │     │
│  └─────────────┘    └─────────────┘    └─────────────┘     │
│                              │                               │
│                     Message Contract                         │
│                      Verification                            │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Tests use Testcontainers to spin up a Redpanda instance (Kafka-compatible) for each test run, ensuring isolation and reproducibility.

Running Tests

# From repository root
pnpm test:integration

# Or directly
pnpm --filter @fizzbuzz-enterprise/integration-tests test

# Watch mode (useful during development)
pnpm --filter @fizzbuzz-enterprise/integration-tests test:watch

Test Coverage

The integration tests verify message contracts between all service boundaries:

Contract Topic Producer Consumer Status
NumberMessage numbers-topic number-ingestion fizz, buzz Verified
FizzResult fizz-topic fizz-service aggregator Verified
BuzzResult buzz-topic buzz-service aggregator Verified
FizzBuzzResult fizzbuzz-topic aggregator api-service Verified

Directory Structure

tests/
├── README.md                 # This file
└── integration/
    ├── package.json          # Test dependencies
    ├── vitest.config.ts      # Vitest configuration
    ├── tsconfig.json         # TypeScript configuration
    ├── setup/
    │   └── global-setup.ts   # Starts/stops Redpanda container
    └── specs/
        └── message-flow.test.ts  # Contract verification tests

Writing New Tests

Adding a Contract Test

  1. Import fixtures from @fizzbuzz-enterprise/test-utils:
import {
  createNumberMessage,
  createFizzResult,
  type NumberMessage,
  type FizzResult,
} from '@fizzbuzz-enterprise/test-utils';
  1. Use the shared Kafka infrastructure:
describe('My Service Contract', () => {
  it('should produce valid messages', async () => {
    const producer = new TestProducer({ brokers: globalThis.__KAFKA_BROKERS__ });
    await producer.connect();

    const message = createNumberMessage({ number: 42 });
    await producer.send('my-topic', message);

    // Assert consumer receives expected format
    // ...

    await producer.disconnect();
  });
});
  1. Use the consumeOne helper for synchronized consumption:
const result = await consumeOne<MyMessage>({
  topic: 'my-topic',
  sendMessage: async () => {
    await producer.send('my-topic', myMessage);
  },
});

expect(result.value).toMatchObject({
  // expected fields
});

Available Fixtures

The @fizzbuzz-enterprise/test-utils package provides factory functions:

Function Creates
createNumberMessage() Valid NumberMessage with defaults
createFizzResult() Valid FizzResult with defaults
createBuzzResult() Valid BuzzResult with defaults
createFizzBuzzResult() Valid FizzBuzzResult with defaults
generateCorrelationId() UUID v4 correlation ID

All factories accept overrides:

const message = createNumberMessage({
  number: 15,
  correlationId: 'test-123',
});

Test Utilities

Utility Purpose
TestProducer Send messages to Kafka topics
TestConsumer Consume messages with filtering
waitForMessages() Wait for N messages on a topic
waitForCondition() Poll until condition is true
waitForHealthy() Wait for HTTP health endpoint

CI Integration

Integration tests run in GitHub Actions after unit tests pass:

test-integration:
  needs: [test-fizz-service, test-buzz-service, ...]
  timeout-minutes: 10

Tests are triggered when relevant paths change:

  • tests/integration/**
  • packages/test-utils/**
  • packages/kafka-client/**
  • Service source directories

Troubleshooting

Container Startup Timeout

If tests fail with container startup errors:

# Increase Docker resources (memory/CPU)
# Or pull Redpanda image ahead of time:
docker pull redpandadata/redpanda:latest

Consumer Group Issues

If tests hang waiting for messages, ensure:

  1. Topic exists (created in global setup)
  2. Consumer group ID is unique per test
  3. Producer sends after consumer joins group (use consumeOne helper)

Debugging

Enable verbose Kafka logging:

DEBUG=kafkajs:* pnpm test:integration

View container logs:

// In test file
console.log(await container.logs());

References