Reproducible fake data for Unity tests
Seed Mock Magic and fix its date reference to get identical values and series in every test run, then restore random output safely afterwards.

Random data is good at finding input your code did not expect: the 24-character name, the apostrophe in O’Brien, the missing company, the four-digit price. It is bad at helping you fix the bug, because the next run draws different values and the failure is gone. A seed solves that. Mock Magic sends all of its randomness through one generator that you can seed, so a single call makes names, e-mail addresses, GUIDs, series and even the gaps of a stream repeat, and with a fixed date reference whole person records do too.
This page covers the seed, the two pieces of state that sit next to it, the date reference and the ID counter, and how to set and clean up all three in a Unity Test Framework test. How seeds work in UnityEngine.Random, System.Random and Unity.Mathematics is the subject of random seeds in Unity.
Stable mode in the Generator
The Generator header has a Randomness row with Random and Stable. Stable adds a seed field and New Seed. Before every Regenerate in the Values workspace and every Generate Series in the Series workspace, the window calls Mock.Seed with that number and counts dates from 1 January 2026, so the same type, count and seed produce the same list on any day. Switching back to Random or closing the window returns dates to the real clock. The window remembers the mode and the seed between sessions, and New Seed picks another number and regenerates the current workspace.
Because the window uses the public API, code reproduces its output exactly. With seed 2026 and a Count of 10 on the Name type, Mock.Seed(2026) followed by Mock.Generate(SimpleDataType.Name, 10) returns the same ten names; for date types, add Mock.UseDateReference(new DateTime(2026, 1, 1)). The window sets this shared state while it is open in Stable mode, so Editor scripts that call Mock Magic meanwhile see the seed and the date as well. Tests that set both in their own setup, as below, are unaffected.
Seed in code
using MockMagic;using UnityEngine;
public static class SeedCheck{ public static void Run() { Mock.Seed(2026); string first = string.Join(", ", Mock.Names(3));
Mock.Seed(2026); string second = string.Join(", ", Mock.Names(3));
Debug.Log(first == second); // True on every run Mock.ResetSeed(); // unseeded values from here on }}The guarantee is “same calls, same order”. Each generator takes a fixed number of draws from the seeded sequence, so one extra call in between, such as a debug line that logs Mock.Name(), changes every value after it. While a seed is active, Mock.Guid() also builds valid version 4 GUIDs from the seeded sequence instead of calling System.Guid.NewGuid(), so even IDs of that kind repeat. Keep in mind that a later version of Mock Magic may change its word lists, so values stored as expected results belong to the package version that produced them. When a fixture must never change, export it once as CSV, JSON or C# and commit the file instead.
Mock Magic and UnityEngine.Random
Mock.Seed also calls UnityEngine.Random.InitState with the same number. That is deliberate: code that mixes Mock Magic with Random.Range, for example names from Mock Magic and spawn positions from Unity, repeats as a whole. Mock.ResetSeed then gives UnityEngine.Random fresh randomness again, so tests that run afterwards do not inherit a predictable sequence. It does not bring back a sequence your own code had seeded before; if that matters, save UnityEngine.Random.state before Mock.Seed and assign it back afterwards.
Pin the date
A seed fixes the random draws, not the clock. Mock.Date(), Mock.DateTime() and Mock.Timestamp() are offsets from the current time, so a seeded test still gets other dates tomorrow. MockPerson.New() counts from the same point: its birth date always gives exactly the person’s Age on that day, leap days included. Two methods fix the point they all count from:
Mock.UseDateReference(new DateTime(2026, 11, 11))counts from a fixed day.Mock.UseDateReferenceProvider(() => calendar.Today)asks a function on every call, for example your game’s own calendar.Mock.UseDateReference(null)returns to the real clock.
With a seed and a fixed date, seeded people repeat down to their birthdays. Mock.ResetSeed does not clear the date reference and Mock.Seed does not set one, so treat them as two separate settings. Entering Play Mode clears both, which is one more reason to set them inside the test or its setup rather than once from an Editor script.
Keep IDs predictable
Mock.Id() counts up and shares its counter with the {{id}} and {{unique}} template tokens. Mock.Seed and Mock.ResetSeed both restart that counter, so the first Mock.Id() after seeding returns 1. For another start, call Mock.ResetIdCounter after Mock.Seed: Mock.ResetIdCounter(5000) makes the next ID 5000 and leaves the seed and its random sequence alone. Zero and negative start values work too. Inside a MockOf<T> builder, the index overload of Set, such as .Set((order, i) => order.Id = 5000 + i), gives each record its position without touching the shared counter.
Separate seeds with MockOf.UseSeed
UseSeed(7) on a MockOf<T> builder seeds only that builder’s Generate or GenerateLazy pass. Afterwards it restores the previous random state, seed and ID counter, UnityEngine.Random included, so code outside the builder keeps its own sequence. That keeps data sets independent: build customers with UseSeed(1) and orders with UseSeed(2), and a new field on the customer no longer shifts every order, with nothing to reset afterwards.
Order matters
Put together, the rules give one sequence:
- Call
Mock.Seed, which also seedsUnityEngine.Randomand restarts IDs at 1. - If IDs should start elsewhere, call
Mock.ResetIdCounternow, after the seed. - Set the date reference.
- Generate in a fixed order.
- Afterwards, call
Mock.ResetSeedandMock.UseDateReference(null).
A Unity Test Framework example
A test assembly only sees Mock Magic after you add its runtime assembly, com.wetzold.mock-magic, to the references of your test assembly definition. SetUp and TearDown then wrap every test in the sequence above:
using System;using System.Globalization;using MockMagic;using NUnit.Framework;
public class CustomerCardTests{ static readonly DateTime Today = new DateTime(2026, 11, 11);
[SetUp] public void SetUp() { Mock.Seed(2026); // also seeds UnityEngine.Random and restarts Mock.Id() at 1 Mock.UseDateReference(Today); }
[TearDown] public void TearDown() { Mock.ResetSeed(); Mock.UseDateReference(null); }
[Test] public void InitialsAreTwoCapitals() { foreach (string name in Mock.Names(500)) Assert.That(Initials(name), Does.Match(@"^\p{Lu}\p{Lu}$"), name); }
[Test] public void AgeMatchesTheBirthDate() { foreach (MockPerson person in MockPerson.New(300)) Assert.That(AgeOn(Today, person.DateOfBirth), Is.EqualTo(person.Age), person.DateOfBirth); }
[Test] public void DaysSinceLastOrderIsNeverNegative() { foreach (string date in Mock.Dates(200, yearsBack: 2, yearsForward: 0)) Assert.That((Today - Parse(date)).Days, Is.GreaterThanOrEqualTo(0), date); }
[Test] public void SameSeedRepeatsTheData() { string[] first = Mock.Emails(5); Mock.Seed(2026); Assert.That(Mock.Emails(5), Is.EqualTo(first)); }
// The helpers under test: in a real project they live in your UI code. static string Initials(string fullName) { string[] parts = fullName.Split(' '); return $"{parts[0][0]}{parts[parts.Length - 1][0]}"; }
static int AgeOn(DateTime day, string isoBirthDate) { DateTime birth = Parse(isoBirthDate); int age = day.Year - birth.Year; if (birth > day.AddYears(-age)) age--; return age; }
static DateTime Parse(string isoDate) => DateTime.ParseExact(isoDate, "yyyy-MM-dd", CultureInfo.InvariantCulture);}When InitialsAreTwoCapitals fails, the message names the value that broke it, and because the seed is fixed, the same name fails again on the next run. Names such as Ava van den Berg are the reason the helper takes the last word instead of the second. AgeMatchesTheBirthDate checks your own age calculation against 300 people whose birth dates and ages agree by construction. DaysSinceLastOrderIsNeverNegative shows why the date reference matters: without it, the generated dates would count from the real clock while the test counts from Today, and it would start failing as soon as the real date moves past November 11, 2026.
For the data itself, realistic test data for Unity UI and patterned chart data show what to seed.
Frequently asked questions
How do I make random test data reproducible in Unity?
Call Mock.Seed with a fixed number before generating, and Mock.UseDateReference with a fixed date if the data contains dates. With the same Mock Magic version, the same calls in the same order then return the same values on every run.
Does Mock.Seed change UnityEngine.Random?
Yes. It also calls UnityEngine.Random.InitState with the same seed, so code that mixes both repeats as a whole. Mock.ResetSeed gives UnityEngine.Random fresh randomness again.
Why do dates still change between runs when I use a seed?
Generated dates, timestamps and the birth dates of MockPerson records count from the current time. Call Mock.UseDateReference with a fixed DateTime so they count from the same day in every run.
Is Stable mode in the Generator the same as Mock.Seed?
It is Mock.Seed plus a fixed date. Before every Regenerate and Generate Series, the window calls Mock.Seed with the number in the seed field and counts dates from 1 January 2026, so a seed repeats its values, dates included, on any day.


