synergy moats product advisory implementations

This commit is contained in:
master
2026-01-17 01:30:03 +02:00
parent 77ff029205
commit d8d9c0a6e3
106 changed files with 20603 additions and 123 deletions

View File

@@ -0,0 +1,195 @@
// -----------------------------------------------------------------------------
// PostgresReportStorageServiceTests.cs
// Sprint: SPRINT_20260117_025_Doctor_coverage_expansion
// Task: DOC-EXP-005 - Persistent Report Storage Tests
// Description: Unit tests for PostgresReportStorageService
// -----------------------------------------------------------------------------
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Moq;
using StellaOps.Doctor.Models;
using StellaOps.Doctor.WebService.Options;
using StellaOps.Doctor.WebService.Services;
using Xunit;
namespace StellaOps.Doctor.WebService.Tests.Services;
public sealed class PostgresReportStorageServiceTests
{
[Fact]
public void Constructor_WithMissingConnectionString_ThrowsException()
{
// Arrange
var config = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>())
.Build();
var options = Options.Create(new DoctorServiceOptions());
var logger = new Mock<ILogger<PostgresReportStorageService>>();
// Act & Assert
Assert.Throws<InvalidOperationException>(() =>
new PostgresReportStorageService(config, options, logger.Object));
}
[Fact]
public void Constructor_WithValidConnectionString_Succeeds()
{
// Arrange
var config = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["ConnectionStrings:StellaOps"] = "Host=localhost;Database=test"
})
.Build();
var options = Options.Create(new DoctorServiceOptions { ReportRetentionDays = 0 });
var logger = new Mock<ILogger<PostgresReportStorageService>>();
// Act
using var service = new PostgresReportStorageService(config, options, logger.Object);
// Assert
Assert.NotNull(service);
}
[Fact]
public void Constructor_WithRetentionDays_StartsCleanupTimer()
{
// Arrange
var config = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["ConnectionStrings:StellaOps"] = "Host=localhost;Database=test"
})
.Build();
var options = Options.Create(new DoctorServiceOptions { ReportRetentionDays = 30 });
var logger = new Mock<ILogger<PostgresReportStorageService>>();
// Act
using var service = new PostgresReportStorageService(config, options, logger.Object);
// Assert - service should be created without error
Assert.NotNull(service);
}
[Fact]
public void Dispose_CanBeCalledMultipleTimes()
{
// Arrange
var config = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["Database:ConnectionString"] = "Host=localhost;Database=test"
})
.Build();
var options = Options.Create(new DoctorServiceOptions());
var logger = new Mock<ILogger<PostgresReportStorageService>>();
var service = new PostgresReportStorageService(config, options, logger.Object);
// Act & Assert - should not throw
service.Dispose();
service.Dispose();
}
}
/// <summary>
/// Integration tests for PostgresReportStorageService.
/// These require a PostgreSQL instance and are skipped in CI unless configured.
/// </summary>
public sealed class PostgresReportStorageServiceIntegrationTests
{
private static bool IsPostgresAvailable()
{
var connString = Environment.GetEnvironmentVariable("STELLA_TEST_POSTGRES");
return !string.IsNullOrEmpty(connString);
}
[Fact(Skip = "Requires PostgreSQL instance")]
public async Task StoreAndRetrieveReport_RoundTrip()
{
if (!IsPostgresAvailable())
{
return;
}
// Arrange
var connString = Environment.GetEnvironmentVariable("STELLA_TEST_POSTGRES")!;
var config = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["ConnectionStrings:StellaOps"] = connString
})
.Build();
var options = Options.Create(new DoctorServiceOptions { ReportRetentionDays = 1 });
var logger = new Mock<ILogger<PostgresReportStorageService>>();
using var service = new PostgresReportStorageService(config, options, logger.Object);
var report = new DoctorReport
{
RunId = $"test-{Guid.NewGuid()}",
StartedAt = DateTimeOffset.UtcNow,
CompletedAt = DateTimeOffset.UtcNow.AddSeconds(5),
OverallSeverity = DoctorSeverity.Pass,
Summary = new DoctorSummary
{
Passed = 5,
Warnings = 1,
Failed = 0,
Skipped = 2,
Info = 1,
Total = 9
},
Results = []
};
// Act
await service.StoreReportAsync(report, CancellationToken.None);
var retrieved = await service.GetReportAsync(report.RunId, CancellationToken.None);
// Assert
Assert.NotNull(retrieved);
Assert.Equal(report.RunId, retrieved.RunId);
Assert.Equal(report.OverallSeverity, retrieved.OverallSeverity);
Assert.Equal(report.Summary.Passed, retrieved.Summary.Passed);
// Cleanup
await service.DeleteReportAsync(report.RunId, CancellationToken.None);
}
[Fact(Skip = "Requires PostgreSQL instance")]
public async Task ListReports_ReturnsPaginatedResults()
{
if (!IsPostgresAvailable())
{
return;
}
// Arrange
var connString = Environment.GetEnvironmentVariable("STELLA_TEST_POSTGRES")!;
var config = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["ConnectionStrings:StellaOps"] = connString
})
.Build();
var options = Options.Create(new DoctorServiceOptions());
var logger = new Mock<ILogger<PostgresReportStorageService>>();
using var service = new PostgresReportStorageService(config, options, logger.Object);
// Act
var reports = await service.ListReportsAsync(limit: 10, offset: 0, CancellationToken.None);
// Assert
Assert.NotNull(reports);
}
}