Demonstrates how to unit test code that uses Replane, using the in-memory test client.
- .NET 8.0 SDK or later
-
Copy this directory to your local machine:
cp -r UnitTesting ~/my-replane-example cd ~/my-replane-example
-
Restore packages:
dotnet restore
dotnet testOr with verbose output:
dotnet test --logger "console;verbosity=detailed"The InMemoryReplaneClient provides the same interface as the real client but stores configs in memory:
using var config = TestClient.Create(new Dictionary<string, object?>
{
["feature-enabled"] = true,
["rate-limit"] = 100
});[Fact]
public void Test_WithSimpleConfig()
{
using var config = TestClient.Create(new Dictionary<string, object?>
{
["discounts-enabled"] = true,
["base-discount-percent"] = 10.0
});
var service = new PricingService(config);
var result = service.CalculateDiscount("user-1", "free", 100m);
Assert.Equal(10m, result);
}Test conditional logic with override rules:
[Fact]
public void Test_WithOverrides()
{
using var config = TestClient.Create();
config.SetConfigWithOverrides(
"premium-bonus",
value: 0.0, // Default for non-premium
overrides:
[
new OverrideData
{
Name = "premium-users",
Conditions =
[
new ConditionData
{
Operator = "in",
Property = "plan",
Expected = new List<object?> { "premium", "enterprise" }
}
],
Value = 10.0 // Bonus for premium users
}
]);
var service = new PricingService(config);
// Free user gets default
Assert.Equal(0.0, service.GetBonus("user-1", "free"));
// Premium user gets override value
Assert.Equal(10.0, service.GetBonus("user-2", "premium"));
}[Fact]
public void Test_Segmentation_IsDeterministic()
{
using var config = TestClient.Create();
config.SetConfigWithOverrides(
"feature",
value: false,
overrides:
[
new OverrideData
{
Name = "rollout",
Conditions =
[
new ConditionData
{
Operator = "segmentation",
Property = "user_id",
FromPercentage = 0,
ToPercentage = 50,
Seed = "feature-rollout"
}
],
Value = true
}
]);
// Same user always gets same result
var result1 = config.Get<bool>("feature", new ReplaneContext { ["user_id"] = "user-123" });
var result2 = config.Get<bool>("feature", new ReplaneContext { ["user_id"] = "user-123" });
Assert.Equal(result1, result2);
}Use Set() to change configs mid-test:
[Fact]
public void Test_ConfigChanges()
{
using var config = TestClient.Create(new Dictionary<string, object?>
{
["feature-enabled"] = false
});
Assert.False(config.Get<bool>("feature-enabled"));
// Change the config
config.Set("feature-enabled", true);
Assert.True(config.Get<bool>("feature-enabled"));
}The test client supports all condition types:
| Operator | Description | Example |
|---|---|---|
equals |
Exact match | plan == "premium" |
in |
Value in list | region in ["us-east", "us-west"] |
not_in |
Value not in list | status not in ["blocked"] |
less_than |
Numeric comparison | age < 18 |
less_than_or_equal |
Numeric comparison | age <= 18 |
greater_than |
Numeric comparison | score > 100 |
greater_than_or_equal |
Numeric comparison | score >= 100 |
segmentation |
Percentage bucketing | 50% of users |
and |
All conditions match | Multiple conditions |
or |
Any condition matches | Multiple conditions |
not |
Negate condition | Inverse logic |
- Use
usingstatements - Dispose the client after each test - Isolate tests - Create a fresh client for each test
- Test edge cases - Test default values, missing configs
- Test overrides - Verify conditional logic works correctly
- Test segmentation distribution - Verify rollout percentages
UnitTesting/
├── Services/
│ └── PricingService.cs # Example service using Replane
├── PricingServiceTests.cs # Unit tests
├── UnitTesting.csproj # Project file
└── README.md