diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 86694c89..cb18656d 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -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 ($?)!" diff --git a/src/Yavsc.Blogs.Tests/BlogApiMappedClaimsTests.cs b/src/Yavsc.Blogs.Tests/BlogApiMappedClaimsTests.cs index f6b46ba9..00e2ea61 100644 --- a/src/Yavsc.Blogs.Tests/BlogApiMappedClaimsTests.cs +++ b/src/Yavsc.Blogs.Tests/BlogApiMappedClaimsTests.cs @@ -14,15 +14,10 @@ namespace Yavsc.Blogs.Tests; [Collection("JwtClaimMapping")] public sealed class BlogApiMappedClaimsTests : -IClassFixture, -IBackendFixture +IClassFixture { private readonly MappedClaimsBlogsWebServerFixture _fixture; - public IReadOnlyList Addresses => throw new NotImplementedException(); - - public IServiceProvider Services => throw new NotImplementedException(); - public BlogApiMappedClaimsTests(MappedClaimsBlogsWebServerFixture fixture) { _fixture = fixture; diff --git a/src/Yavsc.Blogs.Tests/Fixtures/MappedClaimsBlogsWebServerFixture.cs b/src/Yavsc.Blogs.Tests/Fixtures/MappedClaimsBlogsWebServerFixture.cs index 2546de0a..7311ce04 100644 --- a/src/Yavsc.Blogs.Tests/Fixtures/MappedClaimsBlogsWebServerFixture.cs +++ b/src/Yavsc.Blogs.Tests/Fixtures/MappedClaimsBlogsWebServerFixture.cs @@ -25,7 +25,7 @@ public sealed class MappedClaimsBlogsWebServerFixture : IDisposable, IBackendFix { private readonly InMemoryDatabaseRoot _inMemoryRoot = new(); private readonly Dictionary _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) diff --git a/src/Yavsc.Tests.Shared/IBackendFixture.cs b/src/Yavsc.Tests.Shared/IBackendFixture.cs index 4e2f009d..b5040b96 100644 --- a/src/Yavsc.Tests.Shared/IBackendFixture.cs +++ b/src/Yavsc.Tests.Shared/IBackendFixture.cs @@ -1,5 +1,4 @@ - -public interface IBackendFixture +public interface IBackendFixture : IDisposable { /// /// The addresses the fixture bound to. @@ -10,4 +9,5 @@ public interface IBackendFixture /// The service provider for the fixture host. /// IServiceProvider Services { get; } + } diff --git a/src/Yavsc.Tests.Shared/WebHostFixture.cs b/src/Yavsc.Tests.Shared/WebHostFixture.cs index 95b23082..f40da18d 100644 --- a/src/Yavsc.Tests.Shared/WebHostFixture.cs +++ b/src/Yavsc.Tests.Shared/WebHostFixture.cs @@ -30,14 +30,13 @@ namespace Yavsc.Tests.Shared; /// mapping are the responsibility of the subclass, through /// . /// -public abstract class WebHostFixture : IDisposable, IBackendFixture +public abstract class WebHostFixture : IBackendFixture { private static readonly Lazy _selfSignedCertificate = new Lazy(CreateSelfSignedCertificate); private static readonly object _sync = new object(); private static WebApplication? _app; private static bool _isInitialized; - private static int _instanceCount; private static readonly List _sharedAddresses = new(); private static IServiceProvider? _sharedServices; @@ -57,11 +56,12 @@ public abstract class WebHostFixture : IDisposable, IBackendFixture /// successfully and the host is running. 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 d’ajouter 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 d’ajouter 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. 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(); + var server = this.App.Services.GetRequiredService(); var addressFeatures = server.Features.Get(); _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; } }