1. ai
  2. /common mistakes
  3. /testing-ai-code

Testing AI-Generated Code

AI-generated tests often look complete while asserting nothing meaningful. Testing AI code means verifying behavior the model cannot hand-wave away.

Last reviewed: June 2026

Models frequently generate tests that mock the unit under test and pass vacuously. Always read assertions.

Prerequisites

Read Evaluating Model Output and Verifying AI Output.

What Models Fake in Tests

PatternSymptomDetection
Mock everythingexpect(mock).toHaveBeenCalled() onlyNo assertion on return value
Snapshot of mockSnapshot passes when behavior wrongDelete snapshot; write explicit expects
Happy path onlyNo edge casesAsk for null, empty, error inputs
Wrong test runner APITests fail to runRun suite locally
Testing implementationBreaks on refactorPrefer inputs/outputs over internals

Minimum Test Bar by Change Type

ChangeRequired tests
Pure functionUnit tests: happy + 2 edge cases
React componentRender test + key interaction
API routeIntegration test with supertest/fetch
Bug fixRegression test reproducing old bug
RefactorExisting suite must stay green

Workflow

  1. Run existing suite before mergenpm test or project equivalent
  2. Read new tests line by line — every expect must mean something
  3. Break the implementation deliberately — test should fail
  4. Check coverage only where it matters — 100% coverage with weak asserts is worthless
npm test
npm run lint
npm run build

Reference: Jest docs, Vitest docs, Testing Library.

Worked Example: Hollow Test

Bad test (AI-generated)
it("formats currency", () => {
  const format = jest.fn().mockReturnValue("$1.00");
  expect(format()).toBe("$1.00");
});

This tests the mock, not your function.

Good test
import { formatCurrency } from "./formatCurrency";

it("formats USD with two decimals", () => {
  expect(formatCurrency(1099, "USD")).toBe("$10.99");
});

it("returns em dash for null", () => {
  expect(formatCurrency(null, "USD")).toBe("—");
});

Property-Based and Fuzz Checks

For parsers, validators, and serializers, add property tests when feasible:

import fc from "fast-check";

it("round-trips JSON-safe strings", () => {
  fc.assert(
    fc.property(fc.jsonValue(), (value) => {
      expect(parse(serialize(value))).toEqual(value);
    })
  );
});

Libraries: fast-check, Hypothesis (Python).

Integration and E2E

AI often skips integration tests. Require them when:

  • Auth middleware changes
  • Database queries change
  • External webhooks involved

Run E2E sparingly but on critical paths — Playwright, Cypress.

CI Integration for Agent Workflows

When agents run in CI (Agentic Workflows):

GateRule
Unit + integrationMust pass before human merge
New testsHuman reviewer confirms assertions
Flaky testsAgent may not disable tests to green CI
Coverage dropsBlock merge or require justification

Prompts That Produce Better Tests

Write tests for formatCurrency in src/lib/formatCurrency.ts.
Requirements:
- Test real imported function, no mocks of formatCurrency
- Cover null, 0, negative, and large values
- Use project's existing test runner (Vitest)
- Run tests and paste output

For Teams

  • Add "tests assert behavior, not mocks" to Project Rules
  • Require regression test for every AI-assisted bugfix in Team AI Policy
  • Track escaped defects on ai-assisted PRs — tune prompts, not blame individuals