Data Mocking
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
| Group | Option | What it does |
|---|---|---|
| Ranges and lengths | minNumber / maxNumber | Inclusive bounds for generated numbers and bigints. |
| Ranges and lengths | stringLength / maxRandomStringLength | Force, or cap, generated string length. |
| Ranges and lengths | stringCharSet | The character set strings are built from. |
| Ranges and lengths | arrayLength / maxRandomItemsLength | Force, or cap, array, Map, Set and record sizes. The cap shrinks at each nested level. |
| Ranges and lengths | minDate / maxDate | Inclusive bounds for generated dates (a timestamp or a Date). |
| Pools and pins | anyValuesList | The pool the any and unknown kinds draw from. |
| Pools and pins | objectList | The pool the plain object kind draws from. |
| Pools and pins | regexpList | The pool the RegExp kind draws from when nonDataTypes is on. |
| Pools and pins | symbolName / symbolLength / symbolCharSet | Fix a generated symbol's name, or its random length and character set. |
| Pools and pins | unionIndex / enumIndex | Pin a union member or enum branch instead of picking at random. |
| Optionality and recursion | optionalProbability | Chance from 0 to 1 that an optional property is included. |
| Optionality and recursion | optionalPropertyProbability | Per-property override of that chance, keyed by property name. |
| Optionality and recursion | maxMockRecursion | How far a recursive type is followed before it bottoms out. |
| Promises | promiseTimeOut | Delay in milliseconds before a mocked Promise resolves (0 resolves immediately). |
| Promises | promiseReject | When set, the mocked Promise rejects with this value instead of resolving. |
| Advanced | nonDataTypes | Also generate the non-data members (functions, methods, symbols, non-serializable natives) a mock normally leaves out. Off by default. |
| Advanced | tupleOptions / paramsOptions | Per-slot options for a tuple's elements. paramsOptions is an alias that also covers a function's Parameters<typeof fn>. |
| Advanced | seed | Fix 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
patternmocks from itsmockSamples, or from a pool the build generates from the regex when you declare none. - A format's
transform(likeTF.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.