DEV Community

Cover image for Back to Code | Ep 07: The Lies of Mocks — Reality with Testcontainers
Mehmet TURAÇ
Mehmet TURAÇ

Posted on

Back to Code | Ep 07: The Lies of Mocks — Reality with Testcontainers

The 15-week technical battle of LogiFlow — a company waking up from the illusion created by artificial intelligence and returning to real engineering.

The Story

A Redis Lua script exploded in staging. But the Unit Tests were green! Why? Because AI had mocked Redis as an in-memory Map.

The rate limiter was supposed to use a Redis Lua script to atomically check and increment a counter. But the mock was a JavaScript Map. It had no concept of atomicity, no TTL behavior, no cluster mode quirks.

The test passed. The code failed. The mock had lied.

Technical Autopsy: Testcontainers

import { GenericContainer } from 'testcontainers';

describe('RateLimiter (with real Redis)', () => {
  let container: StartedTestContainer;

  beforeAll(async () => {
    container = await new GenericContainer('redis:7-alpine')
      .withExposedPorts(6379)
      .start();
  });

  it('Lua script should execute atomically', async () => {
    const realRedis = createClient({
      url: `redis://${container.getHost()}:${container.getMappedPort(6379)}`
    });
    await realRedis.connect();

    const script = `
      local current = redis.call('GET', KEYS[1])
      if current and tonumber(current) >= tonumber(ARGV[1]) then
        return 0
      end
      redis.call('INCR', KEYS[1])
      redis.call('EXPIRE', KEYS[1], ARGV[2])
      return 1
    `;

    const result = await realRedis.eval(script, {
      keys: ['rate:truck-1'],
      arguments: ['100', '60']
    });

    expect(result).toBe(1);
    await realRedis.disconnect();
  });

  afterAll(async () => {
    await container.stop();
  });
});
Enter fullscreen mode Exit fullscreen mode

Mocks lie. In integration tests, spin up real infrastructure using code.

The Mock Spectrum

Level Tool When to Use
Unit Test Pure functions Domain logic, calculations
Unit Test Interface mocks Use case orchestration
Integration Testcontainers Database queries, cache scripts, message queues
Contract Pact External API agreements
E2E Real environment Full system validation

The mistake isn't using mocks — it's using mocks where they can't represent reality.

Lessons from Episode 7

1. Mock Boundaries: Mocks cannot replicate real infrastructure behavior (TTL, Lua, cluster mode).

2. Testcontainers: Write tests with real Docker containers in your CI/CD pipeline.

3. Contract Testing: Validate contracts with external services using tools like Pact.


This is Episode 7 of the "Back to Code" series. Next up: Episode 8 — The Illusion of Type Safety.

Series: back.to.code · 2026

Top comments (0)