Add comprehensive unit tests for backend services and controllers
- Add API.Tests xUnit project with Moq and EF Core InMemory - Add AgeGroupService tests (CRUD operations, edge cases) - Add RegistrationKeyService tests (CRUD + DeleteOldRegistrationKeys) - Add AgeGroupController tests (all endpoints with mocked service) - Add PlunkEmailSender tests (HTTP client mocking, payload verification) - Add Mapper tests (AltersgruppeMapper, RegistrationKeyMapper) https://claude.ai/code/session_01Kv7Mp2c9FKsHEgQe4BoftH
This commit is contained in:
169
API.Tests/Services/AgeGroupServiceTests.cs
Normal file
169
API.Tests/Services/AgeGroupServiceTests.cs
Normal file
@@ -0,0 +1,169 @@
|
||||
using API.Database;
|
||||
using API.Models.Internal.Altersgruppen;
|
||||
using API.Repository.AgeGroupRepo;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace API.Tests.Services;
|
||||
|
||||
public class AgeGroupServiceTests : IDisposable
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly AgeGroupService _service;
|
||||
|
||||
public AgeGroupServiceTests()
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
|
||||
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
|
||||
.Options;
|
||||
|
||||
_context = new ApplicationDbContext(options);
|
||||
_service = new AgeGroupService(_context);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_context.Database.EnsureDeleted();
|
||||
_context.Dispose();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAllAsync_EmptyDatabase_ReturnsEmptyList()
|
||||
{
|
||||
// Act
|
||||
var result = await _service.GetAllAsync();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Empty(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAllAsync_WithData_ReturnsAllGroups()
|
||||
{
|
||||
// Arrange
|
||||
var group1 = new AltersGruppe { Name = "U10", StartingAge = 8, EndingAge = 10 };
|
||||
var group2 = new AltersGruppe { Name = "U12", StartingAge = 10, EndingAge = 12 };
|
||||
await _context.Altersgruppen.AddRangeAsync(group1, group2);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Act
|
||||
var result = await _service.GetAllAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, result.Count);
|
||||
Assert.Contains(result, g => g.Name == "U10");
|
||||
Assert.Contains(result, g => g.Name == "U12");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAsync_ExistingId_ReturnsGroup()
|
||||
{
|
||||
// Arrange
|
||||
var group = new AltersGruppe { Name = "U14", StartingAge = 12, EndingAge = 14 };
|
||||
await _context.Altersgruppen.AddAsync(group);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Act
|
||||
var result = await _service.GetAsync(group.Id);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal("U14", result.Name);
|
||||
Assert.Equal(12, result.StartingAge);
|
||||
Assert.Equal(14, result.EndingAge);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAsync_NonExistingId_ReturnsNull()
|
||||
{
|
||||
// Act
|
||||
var result = await _service.GetAsync("nonexistent-id");
|
||||
|
||||
// Assert
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateAsync_ValidGroup_AddsToDatabase()
|
||||
{
|
||||
// Arrange
|
||||
var newGroup = new AltersGruppe { Name = "U16", StartingAge = 14, EndingAge = 16 };
|
||||
|
||||
// Act
|
||||
var result = await _service.CreateAsync(newGroup);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal("U16", result.Name);
|
||||
|
||||
var dbGroup = await _context.Altersgruppen.FindAsync(result.Id);
|
||||
Assert.NotNull(dbGroup);
|
||||
Assert.Equal("U16", dbGroup.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateAsync_ExistingGroup_UpdatesProperties()
|
||||
{
|
||||
// Arrange
|
||||
var group = new AltersGruppe { Name = "U18", StartingAge = 16, EndingAge = 18 };
|
||||
await _context.Altersgruppen.AddAsync(group);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var updatedGroup = new AltersGruppe { Name = "U18 Updated", StartingAge = 15, EndingAge = 18 };
|
||||
|
||||
// Act
|
||||
var result = await _service.UpdateAsync(group.Id, updatedGroup);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal("U18 Updated", result.Name);
|
||||
Assert.Equal(15, result.StartingAge);
|
||||
Assert.Equal(18, result.EndingAge);
|
||||
|
||||
var dbGroup = await _context.Altersgruppen.FindAsync(group.Id);
|
||||
Assert.NotNull(dbGroup);
|
||||
Assert.Equal("U18 Updated", dbGroup.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateAsync_NonExistingGroup_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var updatedGroup = new AltersGruppe { Name = "U18 Updated", StartingAge = 15, EndingAge = 18 };
|
||||
|
||||
// Act
|
||||
var result = await _service.UpdateAsync("nonexistent-id", updatedGroup);
|
||||
|
||||
// Assert
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteAsync_ExistingGroup_RemovesFromDatabase()
|
||||
{
|
||||
// Arrange
|
||||
var group = new AltersGruppe { Name = "U20", StartingAge = 18, EndingAge = 20 };
|
||||
await _context.Altersgruppen.AddAsync(group);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Act
|
||||
var result = await _service.DeleteAsync(group.Id);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal("U20", result.Name);
|
||||
|
||||
var dbGroup = await _context.Altersgruppen.FindAsync(group.Id);
|
||||
Assert.Null(dbGroup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteAsync_NonExistingGroup_ReturnsNull()
|
||||
{
|
||||
// Act
|
||||
var result = await _service.DeleteAsync("nonexistent-id");
|
||||
|
||||
// Assert
|
||||
Assert.Null(result);
|
||||
}
|
||||
}
|
||||
214
API.Tests/Services/PlunkEmailSenderTests.cs
Normal file
214
API.Tests/Services/PlunkEmailSenderTests.cs
Normal file
@@ -0,0 +1,214 @@
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using API.Models.Outgoing;
|
||||
using API.Services;
|
||||
using Moq;
|
||||
using Moq.Protected;
|
||||
|
||||
namespace API.Tests.Services;
|
||||
|
||||
public class PlunkEmailSenderTests
|
||||
{
|
||||
private const string TestSecretKey = "test-secret-key";
|
||||
private const string PlunkApiUrl = "https://api.useplunk.com/v1/send";
|
||||
|
||||
private static HttpClient CreateMockHttpClient(HttpStatusCode statusCode, string responseContent = "{}")
|
||||
{
|
||||
var mockHandler = new Mock<HttpMessageHandler>();
|
||||
|
||||
mockHandler
|
||||
.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>(
|
||||
"SendAsync",
|
||||
ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(new HttpResponseMessage
|
||||
{
|
||||
StatusCode = statusCode,
|
||||
Content = new StringContent(responseContent)
|
||||
});
|
||||
|
||||
return new HttpClient(mockHandler.Object);
|
||||
}
|
||||
|
||||
private static (HttpClient client, Mock<HttpMessageHandler> handler) CreateMockHttpClientWithHandler(
|
||||
HttpStatusCode statusCode, string responseContent = "{}")
|
||||
{
|
||||
var mockHandler = new Mock<HttpMessageHandler>();
|
||||
|
||||
mockHandler
|
||||
.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>(
|
||||
"SendAsync",
|
||||
ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(new HttpResponseMessage
|
||||
{
|
||||
StatusCode = statusCode,
|
||||
Content = new StringContent(responseContent)
|
||||
});
|
||||
|
||||
return (new HttpClient(mockHandler.Object), mockHandler);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SendEmailAsync_SuccessfulSend_DoesNotThrow()
|
||||
{
|
||||
// Arrange
|
||||
var httpClient = CreateMockHttpClient(HttpStatusCode.OK);
|
||||
var emailSender = new PlunkEmailSender(httpClient, TestSecretKey);
|
||||
|
||||
// Act & Assert - should not throw
|
||||
await emailSender.SendEmailAsync("test@example.com", "Test Subject", "<p>Test Body</p>");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SendEmailAsync_ApiReturnsError_ThrowsException()
|
||||
{
|
||||
// Arrange
|
||||
var errorMessage = "Invalid API key";
|
||||
var httpClient = CreateMockHttpClient(HttpStatusCode.Unauthorized, errorMessage);
|
||||
var emailSender = new PlunkEmailSender(httpClient, TestSecretKey);
|
||||
|
||||
// Act & Assert
|
||||
var exception = await Assert.ThrowsAsync<Exception>(() =>
|
||||
emailSender.SendEmailAsync("test@example.com", "Test Subject", "<p>Test Body</p>"));
|
||||
|
||||
Assert.Contains("Fehler beim Senden der E-Mail über Plunk", exception.Message);
|
||||
Assert.Contains(errorMessage, exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SendEmailAsync_ServerError_ThrowsException()
|
||||
{
|
||||
// Arrange
|
||||
var httpClient = CreateMockHttpClient(HttpStatusCode.InternalServerError, "Server error");
|
||||
var emailSender = new PlunkEmailSender(httpClient, TestSecretKey);
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<Exception>(() =>
|
||||
emailSender.SendEmailAsync("test@example.com", "Test Subject", "<p>Test Body</p>"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SendEmailAsync_BadRequest_ThrowsException()
|
||||
{
|
||||
// Arrange
|
||||
var httpClient = CreateMockHttpClient(HttpStatusCode.BadRequest, "Invalid request");
|
||||
var emailSender = new PlunkEmailSender(httpClient, TestSecretKey);
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<Exception>(() =>
|
||||
emailSender.SendEmailAsync("test@example.com", "Test Subject", "<p>Test Body</p>"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SendEmailAsync_SendsCorrectPayload()
|
||||
{
|
||||
// Arrange
|
||||
var mockHandler = new Mock<HttpMessageHandler>();
|
||||
HttpRequestMessage? capturedRequest = null;
|
||||
|
||||
mockHandler
|
||||
.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>(
|
||||
"SendAsync",
|
||||
ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.Callback<HttpRequestMessage, CancellationToken>((request, _) => capturedRequest = request)
|
||||
.ReturnsAsync(new HttpResponseMessage
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent("{}")
|
||||
});
|
||||
|
||||
var httpClient = new HttpClient(mockHandler.Object);
|
||||
var emailSender = new PlunkEmailSender(httpClient, TestSecretKey);
|
||||
|
||||
// Act
|
||||
await emailSender.SendEmailAsync("recipient@example.com", "My Subject", "<h1>Hello</h1>");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(capturedRequest);
|
||||
Assert.Equal(HttpMethod.Post, capturedRequest.Method);
|
||||
Assert.Equal(PlunkApiUrl, capturedRequest.RequestUri?.ToString());
|
||||
|
||||
var requestContent = await capturedRequest.Content!.ReadAsStringAsync();
|
||||
var payload = JsonSerializer.Deserialize<PlunkEmailDto>(requestContent, new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true
|
||||
});
|
||||
|
||||
Assert.NotNull(payload);
|
||||
Assert.Equal("recipient@example.com", payload.To);
|
||||
Assert.Equal("My Subject", payload.Subject);
|
||||
Assert.Equal("<h1>Hello</h1>", payload.Body);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SendEmailAsync_SendsCorrectAuthorizationHeader()
|
||||
{
|
||||
// Arrange
|
||||
var mockHandler = new Mock<HttpMessageHandler>();
|
||||
HttpRequestMessage? capturedRequest = null;
|
||||
|
||||
mockHandler
|
||||
.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>(
|
||||
"SendAsync",
|
||||
ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.Callback<HttpRequestMessage, CancellationToken>((request, _) => capturedRequest = request)
|
||||
.ReturnsAsync(new HttpResponseMessage
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent("{}")
|
||||
});
|
||||
|
||||
var httpClient = new HttpClient(mockHandler.Object);
|
||||
var emailSender = new PlunkEmailSender(httpClient, "my-secret-api-key");
|
||||
|
||||
// Act
|
||||
await emailSender.SendEmailAsync("test@example.com", "Subject", "Body");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(capturedRequest);
|
||||
var authHeader = httpClient.DefaultRequestHeaders.Authorization;
|
||||
Assert.NotNull(authHeader);
|
||||
Assert.Equal("Bearer", authHeader.Scheme);
|
||||
Assert.Equal("my-secret-api-key", authHeader.Parameter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SendEmailAsync_SendsCorrectContentType()
|
||||
{
|
||||
// Arrange
|
||||
var mockHandler = new Mock<HttpMessageHandler>();
|
||||
HttpRequestMessage? capturedRequest = null;
|
||||
|
||||
mockHandler
|
||||
.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>(
|
||||
"SendAsync",
|
||||
ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.Callback<HttpRequestMessage, CancellationToken>((request, _) => capturedRequest = request)
|
||||
.ReturnsAsync(new HttpResponseMessage
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent("{}")
|
||||
});
|
||||
|
||||
var httpClient = new HttpClient(mockHandler.Object);
|
||||
var emailSender = new PlunkEmailSender(httpClient, TestSecretKey);
|
||||
|
||||
// Act
|
||||
await emailSender.SendEmailAsync("test@example.com", "Subject", "Body");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(capturedRequest);
|
||||
Assert.NotNull(capturedRequest.Content);
|
||||
Assert.Equal("application/json", capturedRequest.Content.Headers.ContentType?.MediaType);
|
||||
Assert.Equal("utf-8", capturedRequest.Content.Headers.ContentType?.CharSet);
|
||||
}
|
||||
}
|
||||
244
API.Tests/Services/RegistrationKeyServiceTests.cs
Normal file
244
API.Tests/Services/RegistrationKeyServiceTests.cs
Normal file
@@ -0,0 +1,244 @@
|
||||
using API.Database;
|
||||
using API.Models.Internal.User;
|
||||
using API.Repository.RegistrationKeyRepo;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace API.Tests.Services;
|
||||
|
||||
public class RegistrationKeyServiceTests : IDisposable
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly RegistrationKeyService _service;
|
||||
|
||||
public RegistrationKeyServiceTests()
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
|
||||
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
|
||||
.Options;
|
||||
|
||||
_context = new ApplicationDbContext(options);
|
||||
_service = new RegistrationKeyService(_context);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_context.Database.EnsureDeleted();
|
||||
_context.Dispose();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAllAsync_EmptyDatabase_ReturnsEmptyList()
|
||||
{
|
||||
// Act
|
||||
var result = await _service.GetAllAsync();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Empty(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAllAsync_WithData_ReturnsAllKeys()
|
||||
{
|
||||
// Arrange
|
||||
var key1 = new RegistrationKey { LinkedRole = "Admin" };
|
||||
var key2 = new RegistrationKey { LinkedRole = "User" };
|
||||
await _context.RegistrationKeys.AddRangeAsync(key1, key2);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Act
|
||||
var result = await _service.GetAllAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, result.Count);
|
||||
Assert.Contains(result, k => k.LinkedRole == "Admin");
|
||||
Assert.Contains(result, k => k.LinkedRole == "User");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAsync_ExistingId_ReturnsKey()
|
||||
{
|
||||
// Arrange
|
||||
var key = new RegistrationKey { LinkedRole = "Moderator" };
|
||||
await _context.RegistrationKeys.AddAsync(key);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Act
|
||||
var result = await _service.GetAsync(key.Id);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal("Moderator", result.LinkedRole);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAsync_NonExistingId_ReturnsNull()
|
||||
{
|
||||
// Act
|
||||
var result = await _service.GetAsync("nonexistent-id");
|
||||
|
||||
// Assert
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateAsync_ValidKey_AddsToDatabase()
|
||||
{
|
||||
// Arrange
|
||||
var keyIngoing = new RegistrationKeyIngoing { LinkedRole = "Admin" };
|
||||
|
||||
// Act
|
||||
var result = await _service.CreateAsync(keyIngoing);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal("Admin", result.LinkedRole);
|
||||
Assert.NotNull(result.Id);
|
||||
|
||||
var dbKey = await _context.RegistrationKeys.FindAsync(result.Id);
|
||||
Assert.NotNull(dbKey);
|
||||
Assert.Equal("Admin", dbKey.LinkedRole);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateAsync_NullRole_AddsToDatabase()
|
||||
{
|
||||
// Arrange
|
||||
var keyIngoing = new RegistrationKeyIngoing { LinkedRole = null };
|
||||
|
||||
// Act
|
||||
var result = await _service.CreateAsync(keyIngoing);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Null(result.LinkedRole);
|
||||
|
||||
var dbKey = await _context.RegistrationKeys.FindAsync(result.Id);
|
||||
Assert.NotNull(dbKey);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteAsync_ExistingKey_RemovesFromDatabase()
|
||||
{
|
||||
// Arrange
|
||||
var key = new RegistrationKey { LinkedRole = "ToDelete" };
|
||||
await _context.RegistrationKeys.AddAsync(key);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Act
|
||||
var result = await _service.DeleteAsync(key.Id);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal("ToDelete", result.LinkedRole);
|
||||
|
||||
var dbKey = await _context.RegistrationKeys.FindAsync(key.Id);
|
||||
Assert.Null(dbKey);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteAsync_NonExistingKey_ReturnsNull()
|
||||
{
|
||||
// Act
|
||||
var result = await _service.DeleteAsync("nonexistent-id");
|
||||
|
||||
// Assert
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteOldRegistrationKeysAsync_ZeroDays_ReturnsZero()
|
||||
{
|
||||
// Arrange
|
||||
var key = new RegistrationKey { LinkedRole = "Old", Created = DateTime.UtcNow.AddDays(-10) };
|
||||
await _context.RegistrationKeys.AddAsync(key);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Act
|
||||
var result = await _service.DeleteOldRegistrationKeysAsync(0);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(0, result);
|
||||
Assert.Single(await _context.RegistrationKeys.ToListAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteOldRegistrationKeysAsync_NegativeDays_ReturnsZero()
|
||||
{
|
||||
// Arrange
|
||||
var key = new RegistrationKey { LinkedRole = "Old", Created = DateTime.UtcNow.AddDays(-10) };
|
||||
await _context.RegistrationKeys.AddAsync(key);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Act
|
||||
var result = await _service.DeleteOldRegistrationKeysAsync(-5);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(0, result);
|
||||
Assert.Single(await _context.RegistrationKeys.ToListAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteOldRegistrationKeysAsync_NoOldKeys_ReturnsZero()
|
||||
{
|
||||
// Arrange
|
||||
var key = new RegistrationKey { LinkedRole = "New", Created = DateTime.UtcNow };
|
||||
await _context.RegistrationKeys.AddAsync(key);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Act
|
||||
var result = await _service.DeleteOldRegistrationKeysAsync(7);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(0, result);
|
||||
Assert.Single(await _context.RegistrationKeys.ToListAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteOldRegistrationKeysAsync_WithOldKeys_DeletesOldKeysOnly()
|
||||
{
|
||||
// Arrange
|
||||
var oldKey1 = new RegistrationKey { LinkedRole = "Old1", Created = DateTime.UtcNow.AddDays(-10) };
|
||||
var oldKey2 = new RegistrationKey { LinkedRole = "Old2", Created = DateTime.UtcNow.AddDays(-15) };
|
||||
var newKey = new RegistrationKey { LinkedRole = "New", Created = DateTime.UtcNow.AddDays(-2) };
|
||||
|
||||
await _context.RegistrationKeys.AddRangeAsync(oldKey1, oldKey2, newKey);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Act
|
||||
var result = await _service.DeleteOldRegistrationKeysAsync(7);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, result);
|
||||
|
||||
var remainingKeys = await _context.RegistrationKeys.ToListAsync();
|
||||
Assert.Single(remainingKeys);
|
||||
Assert.Equal("New", remainingKeys[0].LinkedRole);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteOldRegistrationKeysAsync_ExactCutoffDate_KeyNotDeleted()
|
||||
{
|
||||
// Arrange - key created exactly at cutoff should NOT be deleted
|
||||
var keyAtCutoff = new RegistrationKey { LinkedRole = "AtCutoff", Created = DateTime.UtcNow.AddDays(-7) };
|
||||
await _context.RegistrationKeys.AddAsync(keyAtCutoff);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Act
|
||||
var result = await _service.DeleteOldRegistrationKeysAsync(7);
|
||||
|
||||
// Assert - cutoff is < not <=, so exactly 7 days old should not be deleted
|
||||
Assert.Equal(0, result);
|
||||
Assert.Single(await _context.RegistrationKeys.ToListAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteOldRegistrationKeysAsync_EmptyDatabase_ReturnsZero()
|
||||
{
|
||||
// Act
|
||||
var result = await _service.DeleteOldRegistrationKeysAsync(7);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(0, result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user