Disposing the test fixtures
All checks were successful
Dotnet build and test / build (push) Successful in 6m49s

This commit is contained in:
Paul Schneider 2026-08-29 04:00:10 +01:00
commit 243c0f2780
Signed by: notazof
GPG key ID: 1DD5D838E5343B06
5 changed files with 26 additions and 28 deletions

View file

@ -44,4 +44,4 @@ jobs:
- name: Test
run: |
echo "🚀 Lancement des tests..."
cd /src/_src && dotnet test --verbosity normal && echo "✅ Success !"
cd /src/_src && dotnet test --verbosity normal && echo "✅ Success !" || echo "❌ Fail ($?)!"

View file

@ -14,15 +14,10 @@ namespace Yavsc.Blogs.Tests;
[Collection("JwtClaimMapping")]
public sealed class BlogApiMappedClaimsTests :
IClassFixture<MappedClaimsBlogsWebServerFixture>,
IBackendFixture
IClassFixture<MappedClaimsBlogsWebServerFixture>
{
private readonly MappedClaimsBlogsWebServerFixture _fixture;
public IReadOnlyList<string> Addresses => throw new NotImplementedException();
public IServiceProvider Services => throw new NotImplementedException();
public BlogApiMappedClaimsTests(MappedClaimsBlogsWebServerFixture fixture)
{
_fixture = fixture;

View file

@ -25,7 +25,7 @@ public sealed class MappedClaimsBlogsWebServerFixture : IDisposable, IBackendFix
{
private readonly InMemoryDatabaseRoot _inMemoryRoot = new();
private readonly Dictionary<string, string> _savedInboundMap;
private readonly WebApplication _app;
private WebApplication? _app = null;
public MappedClaimsBlogsWebServerFixture()
{
@ -86,6 +86,7 @@ public sealed class MappedClaimsBlogsWebServerFixture : IDisposable, IBackendFix
public void Dispose()
{
if (_app is null) return;
_app.StopAsync().GetAwaiter().GetResult();
_app.DisposeAsync().AsTask().GetAwaiter().GetResult();
@ -96,6 +97,7 @@ public sealed class MappedClaimsBlogsWebServerFixture : IDisposable, IBackendFix
}
}
private sealed class NoopFileSystemAuthManager : IFileSystemAuthManager
{
public FileAccessRight GetFilePathAccess(System.Security.Claims.ClaimsPrincipal user, string fileRelativePath)

View file

@ -1,5 +1,4 @@
public interface IBackendFixture
public interface IBackendFixture : IDisposable
{
/// <summary>
/// The addresses the fixture bound to.
@ -10,4 +9,5 @@ public interface IBackendFixture
/// The service provider for the fixture host.
/// </summary>
IServiceProvider Services { get; }
}

View file

@ -30,14 +30,13 @@ namespace Yavsc.Tests.Shared;
/// mapping are the responsibility of the subclass, through
/// <see cref="BuildApp"/>.
/// </summary>
public abstract class WebHostFixture : IDisposable, IBackendFixture
public abstract class WebHostFixture : IBackendFixture
{
private static readonly Lazy<X509Certificate2> _selfSignedCertificate =
new Lazy<X509Certificate2>(CreateSelfSignedCertificate);
private static readonly object _sync = new object();
private static WebApplication? _app;
private static bool _isInitialized;
private static int _instanceCount;
private static readonly List<string> _sharedAddresses = new();
private static IServiceProvider? _sharedServices;
@ -57,11 +56,12 @@ public abstract class WebHostFixture : IDisposable, IBackendFixture
/// successfully and the host is running.</summary>
public bool IsInitialized { get; private set; }
#pragma warning disable CS8618 // Un champ non-nullable doit contenir une valeur autre que Null lors de la fermeture du constructeur. Envisagez dajouter le modificateur « required » ou de déclarer le champ comme pouvant accepter la valeur Null.
protected WebHostFixture()
#pragma warning restore CS8618 // Un champ non-nullable doit contenir une valeur autre que Null lors de la fermeture du constructeur. Envisagez dajouter le modificateur « required » ou de déclarer le champ comme pouvant accepter la valeur Null.
{
lock (_sync)
{
_instanceCount++;
if (!_isInitialized)
{
InitializeAsync().GetAwaiter().GetResult();
@ -110,6 +110,8 @@ public abstract class WebHostFixture : IDisposable, IBackendFixture
/// listen port.</summary>
protected virtual int HttpsPort => 5101;
public WebApplication App { get; private set; }
private async Task InitializeAsync()
{
var builder = WebApplication.CreateBuilder();
@ -122,14 +124,14 @@ public abstract class WebHostFixture : IDisposable, IBackendFixture
});
});
var app = BuildApp(builder);
app = await ConfigurePipelineAsync(app);
await app.StartAsync();
this.App = BuildApp(builder);
this.App = await ConfigurePipelineAsync(this.App);
await this.App.StartAsync();
_app = app;
_sharedServices = app.Services;
_app = this.App;
_sharedServices = this.App.Services;
var server = app.Services.GetRequiredService<IServer>();
var server = this.App.Services.GetRequiredService<IServer>();
var addressFeatures = server.Features.Get<IServerAddressesFeature>();
_sharedAddresses.Clear();
if (addressFeatures?.Addresses is not null)
@ -147,15 +149,14 @@ public abstract class WebHostFixture : IDisposable, IBackendFixture
{
lock (_sync)
{
_instanceCount--;
if (_instanceCount == 0 && _app is not null)
{
_app.StopAsync().GetAwaiter().GetResult();
_app = null;
_isInitialized = false;
_sharedAddresses.Clear();
_sharedServices = null;
}
if (!IsInitialized)
throw new InvalidOperationException("Cannot tear down a fixture that has not been initialized.");
this.App.StopAsync().GetAwaiter().GetResult();
IsInitialized = false;
_isInitialized = false;
_sharedAddresses.Clear();
_sharedServices = null;
}
}