I have some sample c# code that demonstrates feature management in .net core.
I have this class that exposes an endpoint:
namespace Widgets.Controllers
{
[Authorize]
public class FeatureToggleSampleController : ControllerBase
{
private readonly IFeatureManagerSnapshot featureManager;
public FeatureToggleSampleController(
IFeatureManagerSnapshot featureManager)
{
this.featureManager = featureManager;
}
[Route("toggles/demo")]
[HttpGet]
[FeatureGate(nameof(WidgetToggles.sampleToggleName))]
public string ShowSampleToggle(MeFunctionsRequest request)
{
return "sample toggle is enabled";
}
}
}
we are using a filter, to have the feature mana
[FilterAlias("WidgetsFeatures")]
public class WidgetFeaturesFilter : IWidgetFeaturesFilter
{
private readonly IServiceScopeFactory scopeFactory;
public WidgetFeaturesFilter(IServiceScopeFactory scopeFactory)
{
this.scopeFactory = scopeFactory;
}
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
{
using var scope = scopeFactory.CreateScope();
var featureRepo = scope.ServiceProvider.GetService<IGenericRepository<WidgetFeature>>();
var feature = featureRepo.Retrieve(filter: "[Name] = @FeatureName", filterParameters: new { context.FeatureName }).FirstOrDefault();
return Task.FromResult(feature != null && feature.Enabled);
}
}
In our startup, we add the service like this:
services.AddFeatureManagement(Configuration.GetSection("FeatureManagement")).AddFeatureFilter<WidgetsFeaturesFilter>();
And, this is the json file where we define the toggles:
{
"FeatureManagement": {
"sampleToggleName": {
"EnabledFor": [
{
"Name": "WidgetsFeatures"
}
]
}
}
}
When the bool is true in the database, hitting http://localhost/toggles/demo returns the "sample toggle is enabled" method message. And when I change the value in the database to false, it 404s in the browser. Everything seems to be working as far as the toggle logic itself.
Now I want to demo how to unit test controllers and other modules that use feature toggles.
So far I have written two unit test code based on a sample i found. The first one works - although I'm not sure if it's because i've written the test correctly. But gives me the string I'm looking for.
The second one fails because the mock is not working. I've asked the mockFeatureManager to return false as far as the toggle status, but it still behaves as if the toggle is enabled.
[Collection("UnitTests")]
public class FeatureToggleSampleControllerShould
{
[Fact]
public async void Return_String_If_Toggle_Enabled()
{
var mockFeatureManager = new Mock<IFeatureManagerSnapshot>();
mockFeatureManager
.Setup(x=>x.IsEnabledAsync(nameof(WidgetsFeatureToggles.sampleToggleName)))
.Returns(Task.FromResult(true));
var featureManager = mockFeatureManager.Object;
Assert.True(await featureManager.IsEnabledAsync(nameof(WidgetsFeatureToggles.sampleToggleName)));
var sampleControler = new FeatureToggleSampleController(TestHelper.Appsettings,featureManager);
Assert.Equal("sample toggle is enabled",sampleControler.ShowSampleToggle());
}
[Fact]
public async void Return_404_If_Toggle_Enabled()
{
var mockFeatureManager = new Mock<IFeatureManagerSnapshot>();
mockFeatureManager
.Setup(x=>x.IsEnabledAsync(nameof(WidgetsFeatureToggles.sampleToggleName)))
.Returns(Task.FromResult(false));
var featureManager = mockFeatureManager.Object;
Assert.False(await featureManager.IsEnabledAsync(nameof(WidgetsFeatureToggles.sampleToggleName)));
var sampleControler = new FeatureToggleSampleController(TestHelper.Appsettings,featureManager);
try{
sampleControler.ShowSampleToggle();
} catch (Exception ex) {
Assert.Contains("404",ex.Message);
}
}
}
I don't think the bug is with the actual code, but the unit test. But any tips would be appreciated.
EDIT 2
This was the post I was using as an example: IFeatureManager Unit Testing
In my case, I'm not using azure ...