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
| Pattern | Symptom | Detection |
|---|---|---|
| Mock everything | expect(mock).toHaveBeenCalled() only | No assertion on return value |
| Snapshot of mock | Snapshot passes when behavior wrong | Delete snapshot; write explicit expects |
| Happy path only | No edge cases | Ask for null, empty, error inputs |
| Wrong test runner API | Tests fail to run | Run suite locally |
| Testing implementation | Breaks on refactor | Prefer inputs/outputs over internals |
Minimum Test Bar by Change Type
| Change | Required tests |
|---|---|
| Pure function | Unit tests: happy + 2 edge cases |
| React component | Render test + key interaction |
| API route | Integration test with supertest/fetch |
| Bug fix | Regression test reproducing old bug |
| Refactor | Existing suite must stay green |
Workflow
- Run existing suite before merge —
npm testor project equivalent - Read new tests line by line — every
expectmust mean something - Break the implementation deliberately — test should fail
- 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):
| Gate | Rule |
|---|---|
| Unit + integration | Must pass before human merge |
| New tests | Human reviewer confirms assertions |
| Flaky tests | Agent may not disable tests to green CI |
| Coverage drops | Block 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-assistedPRs — tune prompts, not blame individuals