FakeRandomFixture
Assembly: FEFF.TestFixtures.AspNetCore.dll
Namespace: FEFF.TestFixtures.AspNetCore
Source: FakeRandomFixture.cs
Overview
The FakeRandomFixture is an extension to AppManagerFixture.
It replaces the Random service with a FakeRandom singleton in the application under test, providing deterministic control over random number generation in your tests.
Key Features
- Deterministic Randomness: Default seed of
1for reproducible tests - Configurable Strategies: Override default random generation with custom strategies for different data types
- Thread-Safe: All public methods are thread-safe via
lock() - Automatic Registration: Automatically registers the fake random service with the application's DI container
- Integration with AppManagerFixture: Works seamlessly with other ASP.NET Core fixtures
Basic Usage
First, define your test application entry point:
// ASP.NET Core test application entry point (Program.cs)
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton((_) => Random.Shared);
var app = builder.Build();
// Example endpoint that uses Random
app.MapGet("/random-number", (Random random) =>
{
return random.Next(1, 100);
});
app.Run();
}
}
Note: Random should be registered as a singleton:
builder.Services.AddSingleton((_) => Random.Shared);
Then use the fixture in your tests:
using FEFF.TestFixtures.AspNetCore;
using FEFF.TestFixtures.AspNetCore.Randomness;
public class RandomTests
{
protected IAppClientFixture Client { get; } =
TestContext.Current.GetFeffFixture<AppClientFixture<Program>>();
protected FakeRandomFixture<Program> FakeRandomFx { get; } =
TestContext.Current.GetFeffFixture<FakeRandomFixture<Program>>();
protected FakeRandom FakeRandom => FakeRandomFx.Value;
[Fact]
public async Task RandomNumber__should_respond_with_default_value()
{
// Default behavior uses seed 1
var resp = await Client.LazyValue.GetAsync("/random-number", TestContext.Current.CancellationToken);
var body = await resp.Content.ReadAsStringAsync(TestContext.Current.CancellationToken);
body.Should().Be("42"); // Example expected value
}
[Theory]
[InlineData(11)]
[InlineData(22)]
[InlineData(99)]
public async Task RandomNumber__should_respond_with_custom_value(int expectedValue)
{
// Set the fake random to always return a specific value
FakeRandom.Int32Next = FixedNextStrategy.From(expectedValue);
var resp = await Client.LazyValue.GetAsync("/random-number", TestContext.Current.CancellationToken);
var body = await resp.Content.ReadAsStringAsync(TestContext.Current.CancellationToken);
body.Should().Be($$"""{{expectedValue}}""");
}
}
Type Arguments
| Type Argument | Constraint | Description |
|---|---|---|
TEntryPoint |
class |
The application entry point type. Typically the Startup or Program class. |
Key Members
FakeRandomFixture
| Property | Type | Description |
|---|---|---|
Value |
FakeRandom |
Gets the FakeRandom instance, which can be configured to control random value generation during tests. |
FakeRandom
| Property | Type | Description |
|---|---|---|
Int32Next |
INextStrategy<int>? |
Gets or sets the strategy for generating int values. |
Int64Next |
INextStrategy<long>? |
Gets or sets the strategy for generating long values. |
SingleNext |
INextStrategy<float>? |
Gets or sets the strategy for generating float values. |
DoubleNext |
INextStrategy<double>? |
Gets or sets the strategy for generating double values. |
ByteNext |
INextStrategy<byte>? |
Gets or sets the strategy for generating byte values. |
NormalizationStrategy |
INormalizationStrategy |
Gets or sets the normalization strategy for out-of-range values. |
FakeRandom Deep Dive
The FakeRandom class is a configurable random number generator that extends System.Random and provides fine-grained control over random value generation.
Supported Types
FakeRandom supports the following random value types:
int(32-bit integer)long(64-bit integer)float(single-precision)double(double-precision)byte[](byte arrays)
Default Generation Strategies
By default, FakeRandom uses the standard Next() methods of System.Random initialized with a seed value of 1.
Custom Generation Strategies
You can override the default random behavior by setting custom strategies for each type:
// Example: Configure custom strategies for different types
FakeRandom.Int32Next = FixedNextStrategy.From(42);
FakeRandom.DoubleNext = FixedNextStrategy.From(0.5);
FakeRandom.ByteNext = FixedNextStrategy.From((byte)255);
| Property | Type | Description |
|---|---|---|
Int32Next |
INextStrategy<int>? |
Strategy for generating int values. |
Int64Next |
INextStrategy<long>? |
Strategy for generating long values. |
SingleNext |
INextStrategy<float>? |
Strategy for generating float values. |
DoubleNext |
INextStrategy<double>? |
Strategy for generating double values. |
ByteNext |
INextStrategy<byte>? |
Strategy for generating byte values. |
When a property is null, the default Random behavior is used.
INextStrategy
The INextStrategy<T> interface defines a strategy for generating fake values:
public interface INextStrategy<T>
{
T Next();
}
Built-in Strategies
FixedNextStrategy
Returns a constant fixed value every time:
using FEFF.TestFixtures.AspNetCore.Randomness;
// Create a strategy that always returns 42
FakeRandom.Int32Next = FixedNextStrategy.From(42);
// Or create directly
FakeRandom.Int32Next = new FixedNextStrategy<int>(100);
Factory method FixedNextStrategy.From(value) is the recommended way to create fixed strategies.
Normalization Strategies
When a configured strategy returns a value that violates the method contract (e.g., Next(min, max) where the value is outside the expected range), a normalization strategy handles the situation.
public interface INormalizationStrategy
{
int NormalizeI32(int next, int min, int max);
long NormalizeI64(long next, long min, long max);
float NormalizeSingle(float next);
double NormalizeDouble(double next);
}
Available Normalization Strategies
| Strategy | Behavior |
|---|---|
ThrowNormalization (default) |
Throws InvalidOperationException on out-of-range values. |
ReturnAsIsNormalization |
Returns the value unchanged. |
Using Normalization Strategies
using FEFF.TestFixtures.AspNetCore.Randomness;
// Use default (throws on out-of-range values)
FakeRandom.NormalizationStrategy = new ThrowNormalization();
// Return values as-is without validation
FakeRandom.NormalizationStrategy = new ReturnAsIsNormalization();
Thread Safety
All public methods in FakeRandom are thread-safe via lock(), making it safe to use in parallel test scenarios.
Advanced Usage
Multiple Value Types
You can configure strategies for different types independently:
// Configure int generation
FakeRandom.Int32Next = FixedNextStrategy.From(42);
// Configure double generation
FakeRandom.DoubleNext = FixedNextStrategy.From(0.5);
// Configure byte array generation
FakeRandom.ByteNext = FixedNextStrategy.From((byte)255);
Using ReturnAsIsNormalization
When you need exact control over values without validation:
using FEFF.TestFixtures.AspNetCore.Randomness;
// Allow any value to be returned, even if out of range
FakeRandom.NormalizationStrategy = new ReturnAsIsNormalization();
// This will return 150 even if Next(0, 100) is called
FakeRandom.Int32Next = FixedNextStrategy.From(150);
Tip
You can use extension points and create needed implementations of INextStrategy or INormalizationStrategy, for example:
RoundRobinListNextStrategyAutoIncrementedNextStrategyModuloNormalizationStrategy
See Also
| Link | Description |
|---|---|
| API: FakeRandomFixture | API reference |
| FakeRandomFixtureTests.cs | Unit tests for FakeRandomFixture |
| FakeRandomTests | Unit tests for FakeRandom |
| API Integration Example | Integration test examples using FakeRandomFixture |