Initial commit with inital CMS
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using NSubstitute;
|
||||
using SlpModularCms.Core.Availability;
|
||||
using SlpModularCms.Modules.Availability.Middleware;
|
||||
using Xunit;
|
||||
using FluentAssertions;
|
||||
|
||||
namespace SlpModularCms.Modules.Availability.Tests;
|
||||
|
||||
public class AvailabilityMiddlewareTests
|
||||
{
|
||||
private readonly IAvailabilityService _service;
|
||||
private readonly AvailabilityMiddleware _middleware;
|
||||
private readonly RequestDelegate _next;
|
||||
|
||||
public AvailabilityMiddlewareTests()
|
||||
{
|
||||
_service = Substitute.For<IAvailabilityService>();
|
||||
_next = Substitute.For<RequestDelegate>();
|
||||
_middleware = new AvailabilityMiddleware(_next, NullLogger<AvailabilityMiddleware>.Instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAsync_ShouldAllowRequest_WhenSystemAvailable()
|
||||
{
|
||||
// Arrange
|
||||
var context = new DefaultHttpContext();
|
||||
_service.IsAvailableAsync().Returns(AvailabilityStatus.Available);
|
||||
|
||||
// Act
|
||||
await _middleware.InvokeAsync(context, _service);
|
||||
|
||||
// Assert
|
||||
await _next.Received(1).Invoke(context);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAsync_ShouldBlockRequest_WhenSystemUnavailable()
|
||||
{
|
||||
// Arrange
|
||||
var context = new DefaultHttpContext();
|
||||
context.Response.Body = new MemoryStream();
|
||||
_service.IsAvailableAsync().Returns(AvailabilityStatus.NotAvailable);
|
||||
|
||||
// Act
|
||||
await _middleware.InvokeAsync(context, _service);
|
||||
|
||||
// Assert
|
||||
await _next.DidNotReceive().Invoke(Arg.Any<HttpContext>());
|
||||
context.Response.StatusCode.Should().Be(StatusCodes.Status503ServiceUnavailable);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeAsync_ShouldAllowBypass_ForStatusEndpoint()
|
||||
{
|
||||
// Arrange
|
||||
var context = new DefaultHttpContext();
|
||||
context.Request.Path = "/api/availability/status";
|
||||
_service.IsAvailableAsync().Returns(AvailabilityStatus.NotAvailable);
|
||||
|
||||
// Act
|
||||
await _middleware.InvokeAsync(context, _service);
|
||||
|
||||
// Assert
|
||||
await _next.Received(1).Invoke(context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
using SlpModularCms.Core.Availability;
|
||||
using SlpModularCms.Core.Data;
|
||||
using SlpModularCms.Core.Identity.Entities;
|
||||
using SlpModularCms.Modules.Availability.Services;
|
||||
using Xunit;
|
||||
using FluentAssertions;
|
||||
using NSubstitute;
|
||||
|
||||
namespace SlpModularCms.Modules.Availability.Tests;
|
||||
|
||||
public class PersistentAvailabilityServiceTests
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly PersistentAvailabilityService _service;
|
||||
|
||||
public PersistentAvailabilityServiceTests()
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
|
||||
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
|
||||
.Options;
|
||||
_context = new ApplicationDbContext(options);
|
||||
|
||||
var availabilityOptions = Substitute.For<IOptions<AvailabilityOptions>>();
|
||||
availabilityOptions.Value.Returns(new AvailabilityOptions { CircuitBreakerSeconds = 30 });
|
||||
|
||||
_service = new PersistentAvailabilityService(_context, availabilityOptions);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IsAvailableAsync_ShouldReturnAvailable_WhenNoStateInDb()
|
||||
{
|
||||
// Act
|
||||
var status = await _service.IsAvailableAsync();
|
||||
|
||||
// Assert
|
||||
status.Should().Be(AvailabilityStatus.Available);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateStatusAsync_ShouldPersistInDb()
|
||||
{
|
||||
// Act
|
||||
await _service.UpdateStatusAsync(AvailabilityStatus.Maintenance, "Maintenance mode", "Admin");
|
||||
|
||||
// Assert
|
||||
var status = await _service.IsAvailableAsync();
|
||||
status.Should().Be(AvailabilityStatus.Maintenance);
|
||||
|
||||
var dbState = await _context.AvailabilityStates.FirstAsync();
|
||||
dbState.Status.Should().Be(AvailabilityStatus.Maintenance);
|
||||
dbState.Message.Should().Be("Maintenance mode");
|
||||
dbState.UpdatedBy.Should().Be("Admin");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CircuitBreaker_ShouldReturnCachedStatus_AfterDatabaseError()
|
||||
{
|
||||
// Deze test is lastig met in-memory DB omdat deze zelden 'failt'.
|
||||
// Maar we kunnen de logica testen door de context te disposen (simulatie van DB error).
|
||||
|
||||
// Arrange
|
||||
await _service.UpdateStatusAsync(AvailabilityStatus.Available, "Reset", "System");
|
||||
_context.Dispose(); // Forceer error op volgende DB call
|
||||
|
||||
// Act
|
||||
var status1 = await _service.IsAvailableAsync(); // Deze zou moeten failen en circuit breaker activeren
|
||||
|
||||
// Assert
|
||||
status1.Should().Be(AvailabilityStatus.Available); // Fallback status
|
||||
|
||||
// Act 2: Circuit breaker is nu actief
|
||||
var status2 = await _service.IsAvailableAsync();
|
||||
status2.Should().Be(AvailabilityStatus.Available); // Direct uit cache
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="FluentAssertions" Version="8.10.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.11" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="10.0.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.9" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.9" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SlpModularCms.Modules.Availability\SlpModularCms.Modules.Availability.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user