Forger Help

Best Practices

Rules of thumb that keep forged tests readable and stable.

1. Assert on shape and constraints, never on random values

Generated values change on every run. Assertions should pin properties of the data, not the data itself:

// ✅ good — stable and meaningful const age = Forger.create<number>({ numberMax: 100 })!; expect(age).toBeLessThanOrEqual(100); // ❌ bad — random value, test fails on the next run const name = Forger.create<string>()!; expect(name).toBe('I8SE1ou3ZD');

When a concrete value is required, generate it once and reuse it as the expected constant (see Cookbook).

2. Pin only what the test is about

createWith is at its best with one or two pinned properties. A chain of ten with() calls is a hand-written fixture in disguise — if a test needs that much concrete data, consider a dedicated builder instead.

3. Prefer literal unions for constrained values

Literal unions ('asc' | 'desc') forge every member reliably; numeric enums cannot roll their 0 member and string enums yield 0 (see Enums). Inside test doubles, literal unions are the safer modeling tool.

4. Keep settings scoped to the call

Pass settings inline or via a named factory local to the suite. Module-level "global" settings objects tend to grow options that are irrelevant to most tests and hide generation behavior from the reader.

const smallNumbers = () => ({ numberMin: 1, numberMax: 9 }); const qty = Forger.create<Item>(smallNumbers())!;

5. Use the non-null assertion consciously

Forger.create<T>()! is idiomatic when the pipeline is verified. If a whole suite suddenly produces undefined, it is a transformer wiring problem, not a library bug — check Installation before debugging the tests.

6. Treat generated trees as leafy

Circular references cut off at circularDepth (default 1) with null beyond. Walk generated structures with that in mind, or build deeper chains explicitly with createWith.

7. Do not use Forger as a mocking framework

Forged functions return random data; they are stubs, not mocks. When a test needs call recording, argument capture, or scripted behavior, use a mocking library for that member and Forger for the surrounding data:

const service = Forger.createWith<PaymentService>() .with(s => s.charge = jest.fn().mockReturnValue(true)) .result()!;

8. Keep production models forging-friendly

Annotate class properties (id: number, not id = 1), prefer function-typed members over methods when the member is data-like, and rely on interfaces at the boundaries. These habits make Forger.create<T>() produce complete fakes without extra configuration.

08 September 2026