Files
Omika/tests/Omika.Diagnostics.Tests/DiagnosticWorkerDependencyInjectionTests.cs
T
2026-10-23 18:46:50 +02:00

124 lines
4.9 KiB
C#

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Omika.Diagnostics.Configuration;
using Omika.Diagnostics.Data;
using Omika.Diagnostics.Import;
using Omika.Diagnostics.Worker;
namespace Omika.Diagnostics.Tests;
/// <summary>
/// Vérifie que le conteneur DI du Diagnostics Worker construit réellement
/// <see cref="DiagnosticImporter"/> et les hosted services (régression de
/// l'incident production « Unable to resolve service for type
/// DiagnosticImportOptions »). Le host est construit avec
/// <c>ValidateOnBuild</c> + <c>ValidateScopes</c> pour détecter ce type d'erreur
/// à la construction (le test échouait avec l'ancien code).
/// </summary>
public class DiagnosticWorkerDependencyInjectionTests
{
[Fact]
public void WorkerHost_ServiceProviderBuilds_WithValidation()
{
// Avec l'ancien constructeur (DiagnosticImportOptions concret), ce Build()
// levait « Unable to resolve service for type DiagnosticImportOptions ».
using IHost host = BuildWorkerHost();
Assert.NotNull(host.Services);
}
[Fact]
public void WorkerHost_DiagnosticImporter_IsResolvable()
{
using IHost host = BuildWorkerHost();
DiagnosticImporter importer = host.Services.GetRequiredService<DiagnosticImporter>();
Assert.NotNull(importer);
}
[Fact]
public void WorkerHost_DiagnosticImportOptions_AreResolvedAndBound()
{
using IHost host = BuildWorkerHost();
DiagnosticImportOptions options = host.Services
.GetRequiredService<IOptions<DiagnosticImportOptions>>()
.Value;
Assert.NotNull(options);
// La configuration in-memory prime sur les valeurs par défaut (BatchSize=100).
Assert.Equal(50, options.BatchSize);
Assert.Equal("import-checkpoint.json", options.CheckpointFileName);
Assert.Equal(@"C:\Omika\Data\DiagnosticsWorker\Checkpoint", options.CheckpointDirectory);
}
[Fact]
public void WorkerHost_DiagnosticStoreOptions_ConnectionStringOverride_Wins()
{
using IHost host = BuildWorkerHost();
DiagnosticStoreOptions store = host.Services
.GetRequiredService<IOptions<DiagnosticStoreOptions>>()
.Value;
// La surcharge standard ConnectionStrings:DiagnosticsDatabase (variable
// d'environnement serveur) prime sur Diagnostics:ConnectionString.
Assert.Equal(
"Host=localhost;Database=omika_diagnostics;Username=diagnostics_worker",
store.ConnectionString);
}
[Fact]
public void WorkerHost_HostedServices_AreResolvable()
{
using IHost host = BuildWorkerHost();
List<IHostedService> hosted = host.Services.GetServices<IHostedService>().ToList();
Assert.Contains(hosted, s => s is DiagnosticImportWorker);
Assert.Contains(hosted, s => s is DiagnosticRetentionWorker);
Assert.Contains(hosted, s => s is DiagnosticTelemetryRetentionWorker);
}
private static IHost BuildWorkerHost()
{
// Configuration in-memory : aucune valeur secrète. La chaîne PostgreSQL
// est un placeholder sans mot de passe (jamais ouverte : les repositories
// sont construits sans connexion).
IConfiguration configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["Diagnostics:ConnectionString"] = "Host=ignored;Database=ignored",
["Diagnostics:Import:BatchSize"] = "50",
["Diagnostics:Import:CheckpointFileName"] = "import-checkpoint.json",
["Diagnostics:Import:CheckpointDirectory"] = @"C:\Omika\Data\DiagnosticsWorker\Checkpoint",
["Observability:Remote:Directory"] = @"C:\Omika\Data\Api\Diagnostics\Jsonl",
// Surcharge standard (serveur) : prime sur Diagnostics:ConnectionString.
["ConnectionStrings:DiagnosticsDatabase"] = "Host=localhost;Database=omika_diagnostics;Username=diagnostics_worker"
})
.Build();
// Reproduit Program.cs du Diagnostics Worker, avec validation DI stricte
// (ValidateOnBuild + ValidateScopes) pour piéger les dépendances non
// enregistrées.
return new HostBuilder()
.UseDefaultServiceProvider(options =>
{
options.ValidateOnBuild = true;
options.ValidateScopes = true;
})
.ConfigureServices(services =>
{
services.AddLogging();
services.AddOmikaDiagnosticData(configuration);
services.AddHostedService<DiagnosticImportWorker>();
services.AddHostedService<DiagnosticRetentionWorker>();
services.AddHostedService<DiagnosticTelemetryRetentionWorker>();
})
.Build();
}
}