too much for one commit
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
using EntKube.Provisioning.Domain;
|
||||
using EntKube.Provisioning.Infrastructure;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EntKube.Provisioning.Tests.Features;
|
||||
|
||||
/// <summary>
|
||||
/// Integration tests for EF Core provisioning repositories. Uses a real SQLite
|
||||
/// database to verify that change tracking works correctly when adding child
|
||||
/// entities with pre-set Guid keys to tracked aggregates.
|
||||
/// </summary>
|
||||
public class EfIdentityRealmRepositoryTests : IDisposable
|
||||
{
|
||||
private readonly SqliteConnection connection;
|
||||
private readonly ProvisioningDbContext db;
|
||||
private readonly EfIdentityRealmRepository repository;
|
||||
|
||||
public EfIdentityRealmRepositoryTests()
|
||||
{
|
||||
connection = new SqliteConnection("DataSource=:memory:");
|
||||
connection.Open();
|
||||
|
||||
DbContextOptions<ProvisioningDbContext> options = new DbContextOptionsBuilder<ProvisioningDbContext>()
|
||||
.UseSqlite(connection)
|
||||
.Options;
|
||||
|
||||
db = new ProvisioningDbContext(options);
|
||||
db.Database.EnsureCreated();
|
||||
repository = new EfIdentityRealmRepository(db);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateAsync_AddingIdentityProvider_DoesNotThrowConcurrencyException()
|
||||
{
|
||||
// Arrange — Create and persist a realm, then load it back.
|
||||
|
||||
Guid environmentId = Guid.NewGuid();
|
||||
Guid clusterId = Guid.NewGuid();
|
||||
|
||||
IdentityRealm realm = IdentityRealm.Create(environmentId, "test-realm", clusterId);
|
||||
await repository.AddAsync(realm);
|
||||
|
||||
IdentityRealm? loaded = await repository.GetByIdAsync(realm.Id);
|
||||
loaded.Should().NotBeNull();
|
||||
|
||||
// Act — Add a new identity provider to the tracked realm and save.
|
||||
// Before the fix, Update() would mark the new provider as Modified
|
||||
// instead of Added, causing DbUpdateConcurrencyException.
|
||||
|
||||
RealmIdentityProvider idp = RealmIdentityProvider.Create(
|
||||
"google", "Google", IdentityProviderType.Google);
|
||||
|
||||
loaded!.AddIdentityProvider(idp);
|
||||
|
||||
Func<Task> act = async () => await repository.UpdateAsync(loaded);
|
||||
|
||||
// Assert — Should save without throwing.
|
||||
|
||||
await act.Should().NotThrowAsync<DbUpdateConcurrencyException>();
|
||||
|
||||
IdentityRealm? reloaded = await repository.GetByIdAsync(realm.Id);
|
||||
reloaded!.IdentityProviders.Should().HaveCount(1);
|
||||
reloaded.IdentityProviders[0].Alias.Should().Be("google");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateAsync_AddingOrganization_DoesNotThrowConcurrencyException()
|
||||
{
|
||||
// Arrange — Create and persist a realm.
|
||||
|
||||
Guid environmentId = Guid.NewGuid();
|
||||
Guid clusterId = Guid.NewGuid();
|
||||
|
||||
IdentityRealm realm = IdentityRealm.Create(environmentId, "org-realm", clusterId);
|
||||
await repository.AddAsync(realm);
|
||||
|
||||
IdentityRealm? loaded = await repository.GetByIdAsync(realm.Id);
|
||||
loaded.Should().NotBeNull();
|
||||
|
||||
// Act — Add a new organization and save.
|
||||
|
||||
RealmOrganization org = RealmOrganization.Create("Engineering", "Dev teams");
|
||||
loaded!.AddOrganization(org);
|
||||
|
||||
Func<Task> act = async () => await repository.UpdateAsync(loaded);
|
||||
|
||||
// Assert
|
||||
|
||||
await act.Should().NotThrowAsync<DbUpdateConcurrencyException>();
|
||||
|
||||
IdentityRealm? reloaded = await repository.GetByIdAsync(realm.Id);
|
||||
reloaded!.Organizations.Should().HaveCount(1);
|
||||
reloaded.Organizations[0].Name.Should().Be("Engineering");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
db.Dispose();
|
||||
connection.Dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user