Add MicCheck.Client library with FeatureClient.IsEnabledAsync
Client-side SDK for checking feature flag state against the flags API, with unit tests mocking HttpMessageHandler.
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using Moq;
|
||||
using Moq.Protected;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace MicCheck.Client.Tests.Unit;
|
||||
|
||||
[TestFixture]
|
||||
public class FeatureClientTests
|
||||
{
|
||||
[Test]
|
||||
public async Task WhenFeatureIsEnabled_ThenIsEnabledAsyncReturnsTrue()
|
||||
{
|
||||
var client = CreateClient(HttpStatusCode.OK, """
|
||||
[{"id":1,"feature":{"id":1,"name":"my-feature","type":"STANDARD"},"enabled":true,"featureStateValue":null}]
|
||||
""");
|
||||
|
||||
var result = await client.IsEnabledAsync("my-feature");
|
||||
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task WhenFeatureIsDisabled_ThenIsEnabledAsyncReturnsFalse()
|
||||
{
|
||||
var client = CreateClient(HttpStatusCode.OK, """
|
||||
[{"id":1,"feature":{"id":1,"name":"my-feature","type":"STANDARD"},"enabled":false,"featureStateValue":null}]
|
||||
""");
|
||||
|
||||
var result = await client.IsEnabledAsync("my-feature");
|
||||
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task WhenFeatureNameDiffersOnlyByCase_ThenIsEnabledAsyncStillMatches()
|
||||
{
|
||||
var client = CreateClient(HttpStatusCode.OK, """
|
||||
[{"id":1,"feature":{"id":1,"name":"My-Feature","type":"STANDARD"},"enabled":true,"featureStateValue":null}]
|
||||
""");
|
||||
|
||||
var result = await client.IsEnabledAsync("my-feature");
|
||||
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task WhenFeatureIsNotFound_ThenIsEnabledAsyncReturnsProvidedDefaultValue()
|
||||
{
|
||||
var client = CreateClient(HttpStatusCode.OK, "[]");
|
||||
|
||||
var result = await client.IsEnabledAsync("missing-feature", defaultValue: true);
|
||||
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenFeatureNameIsEmpty_ThenIsEnabledAsyncThrowsArgumentException()
|
||||
{
|
||||
var client = CreateClient(HttpStatusCode.OK, "[]");
|
||||
|
||||
Assert.That(async () => await client.IsEnabledAsync(" "), Throws.ArgumentException);
|
||||
}
|
||||
|
||||
private static FeatureClient CreateClient(HttpStatusCode responseStatus, string responseBody)
|
||||
{
|
||||
var handler = new Mock<HttpMessageHandler>();
|
||||
handler.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(new HttpResponseMessage(responseStatus)
|
||||
{
|
||||
Content = new StringContent(responseBody, Encoding.UTF8, "application/json")
|
||||
});
|
||||
|
||||
var httpClient = new HttpClient(handler.Object) { BaseAddress = new Uri("https://example.com") };
|
||||
return new FeatureClient(httpClient);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<IsPackable>false</IsPackable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.72" />
|
||||
<PackageReference Include="NUnit" Version="4.5.1" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="6.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../../src/MicCheck.Client/MicCheck.Client.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user