Use when tests need typed factories beyond plain Faker values: FactoryBot for Ruby (traits, associations), Mimesis for Python bulk data, Bogus for .NET Faker<T> builders, or a decision on which generator fits. Shows the same fixture in each tool; faker-data stays the default for simple values.
94%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Reference detail for synthetic-data-toolkit. Bogus is the
canonical .NET test-data generator, ported from faker.js's spirit but typed
for the C#-first ecosystem (bogus-readme). It uses typed
Faker<T> builders with fluent .RuleFor calls per property - the .NET
equivalent of combining Faker's value generation with a factory library's
referential integrity.
Install-Package Bogus(Per bogus-readme; via NuGet.)
For .NET CLI:
dotnet add package Bogususing Bogus;
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public DateTime CreatedAt { get; set; }
}
var faker = new Faker<User>()
.RuleFor(u => u.Id, f => f.IndexFaker)
.RuleFor(u => u.Name, f => f.Name.FullName())
.RuleFor(u => u.Email, f => f.Internet.Email())
.RuleFor(u => u.CreatedAt, f => f.Date.Past());(Adapted from bogus-readme.)
f is a Faker instance (lowercase) exposing the same data-set
modules as the JS / Python ports: f.Name, f.Internet, f.Date,
f.Commerce, f.Address, f.Lorem, f.Random, etc.
f.IndexFaker gives a sequential integer per generation - useful
for IDs that must be unique within a test.
var faker = new Faker<User>()
.StrictMode(true)
.RuleFor(u => u.Id, f => f.IndexFaker)
.RuleFor(u => u.Name, f => f.Name.FullName())
.RuleFor(u => u.Email, f => f.Internet.Email())
.RuleFor(u => u.CreatedAt, f => f.Date.Past());.StrictMode(true) causes Bogus to fail at runtime if any property
of T lacks a RuleFor. Recommended - it prevents silent fixture
drift when a model adds a new property and the factory isn't
updated.
var faker = new Faker<User>()
.RuleFor(u => u.FirstName, f => f.Name.FirstName())
.RuleFor(u => u.LastName, f => f.Name.LastName())
.RuleFor(u => u.FullName, (f, u) => $"{u.FirstName} {u.LastName}") // computed from already-set fields
.RuleFor(u => u.IsActive, f => f.Random.Bool(0.9f)); // 90% activeThe second-argument-form of RuleFor ((f, u) => ...) lets a rule
reference already-generated properties on the same instance - useful
for derived fields.
Per bogus-readme:
| Method | Returns |
|---|---|
faker.Generate() | One T instance. |
faker.Generate(N) | List of N instances. |
faker.GenerateBetween(min, max) | Random count in [min, max]. |
faker.GenerateLazy(N) | Lazy enumerable - generates on iteration; saves memory for large N. |
var oneUser = faker.Generate(); // single
var hundred = faker.Generate(100); // list of 100
var lazyTen = faker.GenerateLazy(10); // IEnumerable<User>; deferredUse GenerateLazy when seeding a database with thousands of rows -
it streams instead of materializing.
var faker = new Faker<Order>()
.UseSeed(1338)
.RuleFor(o => o.Item, f => f.Commerce.Product());(Per bogus-readme.)
UseSeed(int) makes generation reproducible across runs - same
seed produces same data. Mirror the faker-data seeding guidance:
seed in test setup so failures reproduce.
For globally seeding the underlying randomizer (affecting any
non-Faker<T> direct calls):
Randomizer.Seed = new Random(42);var faker = new Faker<User>("de")
.RuleFor(u => u.Name, f => f.Name.FullName());The locale code in the constructor switches data sets. Bogus ships
30+ locales; supported codes match Faker's conventions
(en, de, ja, ko, ru, pt_BR, etc.).
public class UserTests
{
private readonly Faker<User> _userFaker = new Faker<User>("en")
.UseSeed(42)
.StrictMode(true)
.RuleFor(u => u.Name, f => f.Name.FullName())
.RuleFor(u => u.Email, f => f.Internet.Email());
[Fact]
public void User_HasName()
{
var user = _userFaker.Generate();
Assert.NotEmpty(user.Name);
}
}NUnit and MSTest wire identically - Bogus is framework-agnostic.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
RuleFor for some properties only, no StrictMode | New property added; factory silently leaves it default; tests pass against unrealistic state. | Always StrictMode(true). |
Same Faker<T> instance shared across parallel tests | xUnit runs collections in parallel; shared faker = race condition; flaky failures. | Construct per-test (new Faker<T>) or annotate with [Collection("NoParallel")]. |
Hard-coded UseSeed(42) in every factory | Same data in every test = N tests assert against the same name; coincidental passes. | Per-test seed or per-collection seed; document the convention. |
Generate(10000) in unit tests | Slow; CI cost adds up. | Use GenerateLazy(10000) or seed the DB via raw SQL bulk insert. |
Inline new Faker() for every property | The same generator can't share state across properties; randomized values mismatch. | One Faker<T> builder per entity; chain RuleFor calls. |
faker-data
(Python/JS/Ruby), mimesis.md (Python), and
factory-bot.md (Ruby).after(:create) block.Faker<T>, RuleFor,
Generate / GenerateBetween / GenerateLazy, UseSeed.faker-data - the family default for plain field values.