Files
git.stella-ops.org/src/__Libraries/StellaOps.FeatureFlags.Tests/InMemoryFeatureFlagProviderTests.cs
2026-01-13 18:53:39 +02:00

244 lines
6.5 KiB
C#

using FluentAssertions;
using Xunit;
namespace StellaOps.FeatureFlags.Tests;
[Trait("Category", "Unit")]
public class InMemoryFeatureFlagProviderTests
{
[Fact]
public void Name_ReturnsInMemory()
{
// Arrange
var provider = new InMemoryFeatureFlagProvider(new Dictionary<string, bool>());
// Assert
provider.Name.Should().Be("InMemory");
}
[Fact]
public void Priority_ReturnsConfiguredValue()
{
// Arrange
var provider = new InMemoryFeatureFlagProvider(new Dictionary<string, bool>(), priority: 5);
// Assert
provider.Priority.Should().Be(5);
}
[Fact]
public async Task TryGetFlagAsync_ReturnsTrueForEnabledFlag()
{
// Arrange
var flags = new Dictionary<string, bool>
{
{ "enabled-flag", true }
};
var provider = new InMemoryFeatureFlagProvider(flags);
// Act
var result = await provider.TryGetFlagAsync("enabled-flag", FeatureFlagEvaluationContext.Empty);
// Assert
result.Should().NotBeNull();
result!.Enabled.Should().BeTrue();
result.Key.Should().Be("enabled-flag");
}
[Fact]
public async Task TryGetFlagAsync_ReturnsFalseForDisabledFlag()
{
// Arrange
var flags = new Dictionary<string, bool>
{
{ "disabled-flag", false }
};
var provider = new InMemoryFeatureFlagProvider(flags);
// Act
var result = await provider.TryGetFlagAsync("disabled-flag", FeatureFlagEvaluationContext.Empty);
// Assert
result.Should().NotBeNull();
result!.Enabled.Should().BeFalse();
}
[Fact]
public async Task TryGetFlagAsync_ReturnsNullForUnknownFlag()
{
// Arrange
var provider = new InMemoryFeatureFlagProvider(new Dictionary<string, bool>());
// Act
var result = await provider.TryGetFlagAsync("unknown", FeatureFlagEvaluationContext.Empty);
// Assert
result.Should().BeNull();
}
[Fact]
public async Task TryGetFlagAsync_IsCaseInsensitive()
{
// Arrange
var flags = new Dictionary<string, bool>
{
{ "MyFlag", true }
};
var provider = new InMemoryFeatureFlagProvider(flags);
// Act
var result = await provider.TryGetFlagAsync("myflag", FeatureFlagEvaluationContext.Empty);
// Assert
result.Should().NotBeNull();
result!.Enabled.Should().BeTrue();
}
[Fact]
public void SetFlag_AddsNewFlag()
{
// Arrange
var provider = new InMemoryFeatureFlagProvider(new Dictionary<string, bool>());
// Act
provider.SetFlag("new-flag", true);
var result = provider.TryGetFlagAsync("new-flag", FeatureFlagEvaluationContext.Empty).Result;
// Assert
result.Should().NotBeNull();
result!.Enabled.Should().BeTrue();
}
[Fact]
public void SetFlag_UpdatesExistingFlag()
{
// Arrange
var flags = new Dictionary<string, bool>
{
{ "toggle-flag", false }
};
var provider = new InMemoryFeatureFlagProvider(flags);
// Act
provider.SetFlag("toggle-flag", true);
var result = provider.TryGetFlagAsync("toggle-flag", FeatureFlagEvaluationContext.Empty).Result;
// Assert
result.Should().NotBeNull();
result!.Enabled.Should().BeTrue();
}
[Fact]
public void SetFlag_WithVariant_SetsVariantValue()
{
// Arrange
var provider = new InMemoryFeatureFlagProvider(new Dictionary<string, bool>());
// Act
provider.SetFlag("variant-flag", true, "blue");
var result = provider.TryGetFlagAsync("variant-flag", FeatureFlagEvaluationContext.Empty).Result;
// Assert
result.Should().NotBeNull();
result!.Variant.Should().Be("blue");
}
[Fact]
public void RemoveFlag_RemovesExistingFlag()
{
// Arrange
var flags = new Dictionary<string, bool>
{
{ "to-remove", true }
};
var provider = new InMemoryFeatureFlagProvider(flags);
// Act
provider.RemoveFlag("to-remove");
var result = provider.TryGetFlagAsync("to-remove", FeatureFlagEvaluationContext.Empty).Result;
// Assert
result.Should().BeNull();
}
[Fact]
public void RemoveFlag_DoesNotThrowForNonexistentFlag()
{
// Arrange
var provider = new InMemoryFeatureFlagProvider(new Dictionary<string, bool>());
// Act & Assert
provider.Invoking(p => p.RemoveFlag("nonexistent"))
.Should().NotThrow();
}
[Fact]
public void Clear_RemovesAllFlags()
{
// Arrange
var flags = new Dictionary<string, bool>
{
{ "flag-1", true },
{ "flag-2", false }
};
var provider = new InMemoryFeatureFlagProvider(flags);
// Act
provider.Clear();
var result1 = provider.TryGetFlagAsync("flag-1", FeatureFlagEvaluationContext.Empty).Result;
var result2 = provider.TryGetFlagAsync("flag-2", FeatureFlagEvaluationContext.Empty).Result;
// Assert
result1.Should().BeNull();
result2.Should().BeNull();
}
[Fact]
public async Task ListFlagsAsync_ReturnsAllFlags()
{
// Arrange
var flags = new Dictionary<string, bool>
{
{ "flag-a", true },
{ "flag-b", false },
{ "flag-c", true }
};
var provider = new InMemoryFeatureFlagProvider(flags);
// Act
var result = await provider.ListFlagsAsync();
// Assert
result.Should().HaveCount(3);
result.Select(f => f.Key).Should().Contain(["flag-a", "flag-b", "flag-c"]);
}
[Fact]
public async Task ListFlagsAsync_ReturnsEmptyWhenNoFlags()
{
// Arrange
var provider = new InMemoryFeatureFlagProvider(new Dictionary<string, bool>());
// Act
var result = await provider.ListFlagsAsync();
// Assert
result.Should().BeEmpty();
}
[Fact]
public async Task ListFlagsAsync_ReflectsCurrentStateAfterModifications()
{
// Arrange
var provider = new InMemoryFeatureFlagProvider(new Dictionary<string, bool>());
provider.SetFlag("dynamic-flag", true);
// Act
var result = await provider.ListFlagsAsync();
// Assert
result.Should().HaveCount(1);
result.Single().Key.Should().Be("dynamic-flag");
}
}