Files
mic-check/tests/api/MicCheck.Api.Tests.Unit/Features/FeatureUsageQueryServiceTests.cs
James Wampler b4a666ebf0 Refactor nunit tests off EF InMemory provider and web server
Extract IMicCheckDbContext so DB access can be mocked with Moq instead
of the InMemory provider, per project testing guidelines. Add shared
async DbSet test doubles (TestSupport/) to back the mocks. Rewrite
HTTP-pipeline tests (WebApplicationFactory) to exercise controllers
and auth handlers directly instead of running the web server. Drop
DbContext/seeder tests that only made sense against a real provider,
and remove stale duplicate test files left over from a namespace move.
2026-07-04 19:54:22 -07:00

136 lines
5.2 KiB
C#

using MicCheck.Api.Data;
using MicCheck.Api.Features;
using MicCheck.Api.Tests.Unit.TestSupport;
using Moq;
using NUnit.Framework;
namespace MicCheck.Api.Tests.Unit.Features;
[TestFixture]
public class FeatureUsageQueryServiceTests
{
private Mock<IMicCheckDbContext> _db = null!;
private List<FeatureUsageDaily> _usage = null!;
private FeatureUsageQueryService _service = null!;
private const int EnvironmentId = 1;
[SetUp]
public void SetUp()
{
_db = new Mock<IMicCheckDbContext>();
_usage = [];
_db.SetupDbSet(c => c.FeatureUsageDaily, _usage);
_service = new FeatureUsageQueryService(_db.Object);
}
private void SeedUsage(int environmentId, int featureId, string featureName, DateOnly date, long count)
{
_usage.Add(new FeatureUsageDaily
{
EnvironmentId = environmentId,
FeatureId = featureId,
FeatureName = featureName,
UsageDate = date,
Count = count,
UpdatedAt = DateTimeOffset.UtcNow
});
}
[Test]
public async Task WhenNoUsageData_ThenEmptyCollectionsAreReturned()
{
var result = await _service.GetDashboardUsageAsync(EnvironmentId, days: 14);
Assert.That(result.TopFeaturesLastDay, Is.Empty);
Assert.That(result.DailyUsage, Is.Empty);
}
[Test]
public async Task WhenMultipleFeaturesEvaluatedToday_ThenTopFeaturesLastDayOrdersByCountDescending()
{
var today = DateOnly.FromDateTime(DateTime.UtcNow);
SeedUsage(EnvironmentId, featureId: 1, "feature_a", today, count: 50);
SeedUsage(EnvironmentId, featureId: 2, "feature_b", today, count: 200);
SeedUsage(EnvironmentId, featureId: 3, "feature_c", today, count: 10);
var result = await _service.GetDashboardUsageAsync(EnvironmentId, days: 1);
Assert.That(result.TopFeaturesLastDay, Has.Count.EqualTo(3));
Assert.That(result.TopFeaturesLastDay[0].FeatureName, Is.EqualTo("feature_b"));
Assert.That(result.TopFeaturesLastDay[0].Count, Is.EqualTo(200));
Assert.That(result.TopFeaturesLastDay[1].FeatureName, Is.EqualTo("feature_a"));
Assert.That(result.TopFeaturesLastDay[2].FeatureName, Is.EqualTo("feature_c"));
}
[Test]
public async Task WhenMoreThanTenFeatures_ThenTopFeaturesLastDayLimitsToTen()
{
var today = DateOnly.FromDateTime(DateTime.UtcNow);
for (var i = 1; i <= 15; i++)
SeedUsage(EnvironmentId, featureId: i, $"feature_{i}", today, count: i * 10L);
var result = await _service.GetDashboardUsageAsync(EnvironmentId, days: 1);
Assert.That(result.TopFeaturesLastDay, Has.Count.EqualTo(10));
}
[Test]
public async Task WhenUsageSpansMultipleDays_ThenDailyUsageGroupsByDateAscending()
{
var today = DateOnly.FromDateTime(DateTime.UtcNow);
SeedUsage(EnvironmentId, featureId: 1, "flag", today.AddDays(-2), count: 30);
SeedUsage(EnvironmentId, featureId: 1, "flag", today.AddDays(-1), count: 50);
SeedUsage(EnvironmentId, featureId: 1, "flag", today, count: 20);
var result = await _service.GetDashboardUsageAsync(EnvironmentId, days: 7);
Assert.That(result.DailyUsage, Has.Count.EqualTo(3));
Assert.That(result.DailyUsage[0].Date, Is.EqualTo(today.AddDays(-2)));
Assert.That(result.DailyUsage[0].TotalCount, Is.EqualTo(30));
Assert.That(result.DailyUsage[1].TotalCount, Is.EqualTo(50));
Assert.That(result.DailyUsage[2].TotalCount, Is.EqualTo(20));
}
[Test]
public async Task WhenHoveringADay_ThenDailyUsageIncludesPerFeatureBreakdownOrderedByCount()
{
var today = DateOnly.FromDateTime(DateTime.UtcNow);
SeedUsage(EnvironmentId, featureId: 1, "feature_a", today, count: 10);
SeedUsage(EnvironmentId, featureId: 2, "feature_b", today, count: 40);
var result = await _service.GetDashboardUsageAsync(EnvironmentId, days: 1);
var day = result.DailyUsage.Single();
Assert.That(day.TotalCount, Is.EqualTo(50));
Assert.That(day.Features, Has.Count.EqualTo(2));
Assert.That(day.Features[0].FeatureName, Is.EqualTo("feature_b"));
Assert.That(day.Features[0].Count, Is.EqualTo(40));
Assert.That(day.Features[1].FeatureName, Is.EqualTo("feature_a"));
}
[Test]
public async Task WhenUsageExistsOutsideDaysWindow_ThenOldDataIsExcluded()
{
var today = DateOnly.FromDateTime(DateTime.UtcNow);
SeedUsage(EnvironmentId, featureId: 1, "flag", today.AddDays(-30), count: 999);
SeedUsage(EnvironmentId, featureId: 1, "flag", today.AddDays(-3), count: 5);
var result = await _service.GetDashboardUsageAsync(EnvironmentId, days: 7);
Assert.That(result.DailyUsage, Has.Count.EqualTo(1));
Assert.That(result.DailyUsage[0].TotalCount, Is.EqualTo(5));
}
[Test]
public async Task WhenOtherEnvironmentHasUsage_ThenItIsNotIncludedInResults()
{
var today = DateOnly.FromDateTime(DateTime.UtcNow);
SeedUsage(environmentId: 99, featureId: 1, "flag", today, count: 100);
var result = await _service.GetDashboardUsageAsync(EnvironmentId, days: 7);
Assert.That(result.TopFeaturesLastDay, Is.Empty);
Assert.That(result.DailyUsage, Is.Empty);
}
}