Guide

Data Mocking

Generate valid or invalid type-shaped fake data for tests and fixtures.

Generating Mock Data

Mock generation has its own import, so an app that never uses it ships none of it. Change the type and the mocks follow.

import {createMockDataFn} from '@mionjs/run-types/mocking';
// a fresh, valid User on every call
const mockUser = createMockDataFn<User>();

const a = mockUser(); // {id: 91, name: 'qZ...', roles: ['user'], active: true}
const b = mockUser(); // a different one each time

// every mock passes the validator for its type
const isUser = createValidateFn<User>();
isUser(mockUser()); // true
createMockDataFn needs the Vite plugin to read your type, and throws without it. Use it in tests and seed scripts, not in shipped code.

Mock Options

Pass a mock options object to shape the generated values.

// factory options apply to every call; per-call options win (defaults < factory < call)
const mockAccount = createMockDataFn<Account>(undefined, {
  mock: {
    minNumber: 0,
    maxNumber: 1000, // numbers land in [0, 1000]
    stringLength: 8, // every generated string is 8 chars
    optionalProbability: 1, // always include optional props like `tags`
  },
});

const rich = mockAccount({mock: {minNumber: 1_000_000}}); // override just for this call
GroupOptionWhat it does
Ranges and lengthsminNumber / maxNumberInclusive bounds for generated numbers and bigints.
Ranges and lengthsstringLength / maxRandomStringLengthForce, or cap, generated string length.
Ranges and lengthsstringCharSetThe character set strings are built from.
Ranges and lengthsarrayLength / maxRandomItemsLengthForce, or cap, array, Map, Set and record sizes. The cap shrinks at each nested level.
Ranges and lengthsminDate / maxDateInclusive bounds for generated dates (a timestamp or a Date).
Pools and pinsanyValuesListThe pool the any and unknown kinds draw from.
Pools and pinsobjectListThe pool the plain object kind draws from.
Pools and pinsregexpListThe pool the RegExp kind draws from when nonDataTypes is on.
Pools and pinssymbolName / symbolLength / symbolCharSetFix a generated symbol's name, or its random length and character set.
Pools and pinsunionIndex / enumIndexPin a union member or enum branch instead of picking at random.
Optionality and recursionoptionalProbabilityChance from 0 to 1 that an optional property is included.
Optionality and recursionoptionalPropertyProbabilityPer-property override of that chance, keyed by property name.
Optionality and recursionmaxMockRecursionHow far a recursive type is followed before it bottoms out.
PromisespromiseTimeOutDelay in milliseconds before a mocked Promise resolves (0 resolves immediately).
PromisespromiseRejectWhen set, the mocked Promise rejects with this value instead of resolving.
AdvancednonDataTypesAlso generate the non-data members (functions, methods, symbols, non-serializable natives) a mock normally leaves out. Off by default.
AdvancedtupleOptions / paramsOptionsPer-slot options for a tuple's elements. paramsOptions is an alias that also covers a function's Parameters<typeof fn>.
AdvancedseedFix the random source. See Seeding Data.

For realistic values (real names, your own domains, sensible ranges), use the data enrichment map on the MockData page.

Seeding Data

By default every call returns fresh random data. Pass a seed and the same seed always produces the same value, for every type.

const mockFixture = createMockDataFn<Account>(undefined, {mock: {seed: 123}});
const sameEveryRun = mockFixture(); // identical on every run

Time-based values (Date, Temporal, uuid v7) are seeded too: they start from a fixed instant, not the clock, so they still vary but stay the same on every run.

The build also reads a literal seed where the mock is created (createMockDataFn<T>(undefined, {mock: {seed: 42}})). It seeds the value pools of pattern fields with no mockSamples, so pattern mocks stay identical across rebuilds. Without a literal seed those pools change on every build; a computed or per-call seed still makes the picks repeat within one build.

Generating Invalid Data

Set invalid: true to get a value that fails validation: a valid value with one field replaced by a value of the wrong type. Use it to test your validators, decoders and error handling.

// every User this returns fails the validator
const mockBadUser = createMockDataFn<User>(undefined, {mock: {invalid: true}});

const isUser = createValidateFn<User>();
isUser(mockBadUser()); // false  (e.g. {id: 7, email: 12345, role: 'editor', active: true})

// 1 always breaks a single deep field instead of the whole value
const mockBadField = createMockDataFn<User>(undefined, {
  mock: {invalid: true, invalidLeafProbability: 1},
});

invalidLeafProbability (0 to 1) sets how deep the bad value lands: the whole value, a nested object or array, or a leaf. Near the default of 0.85 it breaks a single deep field. Lower it and the break moves outward; at 0 it always replaces the whole value.

Format-Aware Mocks

Mocks respect type formats: an email field gets a real-looking address, not random characters.

const mockContact = createMockDataFn<Contact>();

const fake = mockContact();
// {id: '3f2504e0-4f89-...', email: '[email protected]', name: '...'}

A mock always passes the type's own validator, format checks included. When it cannot (say every sample for a custom pattern breaks the declared length bounds), the mock function throws an error naming the problem.

More format behaviour:

  • A format restricted to a fixed set with allowedValues (the domain formats included) mocks from that set.
  • A custom pattern mocks from its mockSamples, or from a pool the build generates from the regex when you declare none.
  • A format's transform (like TF.Lowercase) is applied to the mock.
  • Two formats that differ only in their mock samples share one compiled entry, so declaring two different sample pools for them is a build error (format-sample-conflict).

Type Formats lists every format and how it mocks.

Copyright © 2026