C# Test Data Generator: Bogus Faker With StrictMode and xUnit
Bogus 35.6.5 generates realistic strings for .NET fixtures, and its `Faker<T>` rule chain is different from every other library in this cluster in one specific way: `StrictMode(true)` throws if you forget to configure a property. This guide shows how to build a deterministic rule chain and why adding a new rule in the middle reshuffles every downstream value.
Libraries confirmed
Bogus StrictMode, AssertConfigurationIsValid, and add-rules-last determinism
Call StrictMode(true) before any RuleFor. A forgotten property then throws a ValidationException at generate time. Validate() returns a bool for unit assertions; AssertConfigurationIsValid() throws on the same gaps when you want an exception rather than a bool. Use Ignore for intentionally unconfigured properties (Bogus docs, retrieved 2026-08-01).
Add new RuleFor rules last. Inserting a rule mid-chain reshuffles the internal random stream for every property that follows, so the same UseSeed produces a different CustomerName sequence. The sample below asserts that before/after difference.
Runnable code sample
Verified against Bogus 35.6.5 docs retrieved 2026-08-01. Copy into your test tree and adjust domain vocabulary as needed.
// NuGet: Bogus 35.6.5 (nuget.org, retrieved 2025-10-25); xUnit [Fact]
using System.Collections.Generic;
using Bogus;
using Xunit;
public enum Channel { Web, Ios, PartnerApi }
public class Subscription
{
public int Id { get; set; }
public string CustomerName { get; set; }
public Channel Channel { get; set; }
public int MonthlySeats { get; set; }
}
public class SubscriptionFakerTests
{
// StrictMode(true) before any RuleFor: unfinished rules fail loudly.
private static Faker<Subscription> Builder() =>
new Faker<Subscription>()
.StrictMode(true)
.RuleFor(s => s.Id, f => f.IndexFaker)
.RuleFor(s => s.CustomerName, f => f.Name.LastName())
.RuleFor(s => s.Channel, f => f.PickRandom<Channel>())
.RuleFor(s => s.MonthlySeats, f => f.Random.Number(1, 250));
[Fact]
public void SameLocalSeedProducesTheSameSubscriptions()
{
List<Subscription> first = Builder().UseSeed(4242).Generate(20);
List<Subscription> second = Builder().UseSeed(4242).Generate(20);
Assert.Equal(
first.ConvertAll(s => s.CustomerName),
second.ConvertAll(s => s.CustomerName));
}
[Fact]
public void EveryPropertyHasARule()
{
// Validate() returns bool; AssertConfigurationIsValid() throws on gaps.
Assert.True(Builder().Validate());
Builder().AssertConfigurationIsValid();
}
[Fact]
public void InsertingARuleMidChainReshufflesDownstreamValues()
{
var threeRules = new Faker<Subscription>()
.StrictMode(true)
.RuleFor(s => s.Id, f => f.IndexFaker)
.RuleFor(s => s.CustomerName, f => f.Name.LastName())
.RuleFor(s => s.Channel, f => f.PickRandom<Channel>())
.RuleFor(s => s.MonthlySeats, f => f.Random.Number(1, 250))
.UseSeed(4242)
.Generate(5);
// New RuleFor inserted before CustomerName: same seed, different names.
var fourRulesInserted = new Faker<Subscription>()
.StrictMode(true)
.RuleFor(s => s.Id, f => f.IndexFaker)
.RuleFor(s => s.MonthlySeats, f => f.Random.Number(1, 250)) // inserted mid-chain
.RuleFor(s => s.CustomerName, f => f.Name.LastName())
.RuleFor(s => s.Channel, f => f.PickRandom<Channel>())
.UseSeed(4242)
.Generate(5);
Assert.NotEqual(
threeRules.ConvertAll(s => s.CustomerName),
fourRulesInserted.ConvertAll(s => s.CustomerName));
}
}When to use Generate-Data instead
Frequently asked questions
Bogus or AutoFixture, and can I use both?
They suit different workflows and can be combined. A DEV Community post (https://dev.to/nausaf/why-i-moved-from-autofixture-to-bogus-for-test-data-generation-for-cxunit-test-49kg, observed 2026-08-01) moved off AutoFixture because "there seems to be no out of the box way of generating a number in a specified range." The AutoFixture repository (https://github.com/AutoFixture/AutoFixture, observed 2026-08-01) shows the feature the same post does not weigh: `[Theory, AutoData]` injects fixture values directly as xUnit theory parameters, which Bogus's rule-chain design has no equivalent of. The `AutoBogus` NuGet package (in the Bogus dependents table, observed 2026-08-01) bridges the two by driving AutoFixture population from Bogus rules. The honest answer: use Bogus where you want named realistic vocabulary and rule completeness enforcement; use AutoFixture's `[AutoData]` where you want declarative parameter injection; use AutoBogus if you want both.
How do I get the same fake data on every test run?
Use `Faker<T>.UseSeed(int)` rather than the global `Randomizer.Seed`. The Bogus docs give two reasons: the global setter affects every faker instance in the process, and its effects are order-dependent on when tests run. Prefer local: call `.UseSeed(4242)` on the specific `Faker<T>` builder you want to be deterministic. For methods that involve dates, also call `.UseDateTimeReference(...)` to pin the reference date, because date methods are relative to today by default. Both confirmed from the Bogus docs via https://github.com/bchavez/Bogus and the Context7 mirror (https://context7.com/bchavez/bogus/llms.txt), retrieved 2026-08-01.
How do I catch a property I forgot to configure?
Call `.StrictMode(true)` before any `.RuleFor` calls. If you call `.Generate()` with a property that has no rule, Bogus throws a `ValidationException` listing the missing property names. For a bool check in a unit test rather than an exception, use `.Validate()` which returns `true` when every property has a rule. Use `.AssertConfigurationIsValid()` when you want the same check to throw. Use `.Ignore(x => x.ComputedProp)` to tell Bogus a property is intentionally unconfigured. `StrictMode`, `Validate`, `AssertConfigurationIsValid`, and `Ignore` were all confirmed from the same Bogus docs, retrieved 2026-08-01.