Browse Source

Add tests for the aggregate root update on foreign key only relations

pull/25937/head
maliming 2 months ago
parent
commit
bad079f145
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 93
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DomainEvents/UpdateAggregateRootWhenNavigationChanges_Tests.cs
  2. 17
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs
  3. 17
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs
  4. 44
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/AppEntityWithNavigations.cs

93
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DomainEvents/UpdateAggregateRootWhenNavigationChanges_Tests.cs

@ -15,6 +15,8 @@ public class UpdateAggregateRootWhenNavigationChanges_Tests : EntityFrameworkCor
{ {
private readonly IRepository<AppEntityWithForeignKeyOnly, Guid> _entityWithForeignKeyOnlyRepository; private readonly IRepository<AppEntityWithForeignKeyOnly, Guid> _entityWithForeignKeyOnlyRepository;
private readonly IRepository<AppEntityWithForeignKeyOnlyChild, Guid> _childRepository; private readonly IRepository<AppEntityWithForeignKeyOnlyChild, Guid> _childRepository;
private readonly IRepository<AppEntityWithForeignKeyOnlyOwner, Guid> _ownerRepository;
private readonly IRepository<AppEntityWithForeignKeyOnlyEntityChild, Guid> _entityChildRepository;
private readonly IRepository<AppEntityWithNavigations, Guid> _entityWithNavigationsRepository; private readonly IRepository<AppEntityWithNavigations, Guid> _entityWithNavigationsRepository;
private readonly IRepository<AppEntityWithNavigationsForeign, Guid> _entityWithNavigationsForeignRepository; private readonly IRepository<AppEntityWithNavigationsForeign, Guid> _entityWithNavigationsForeignRepository;
private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IUnitOfWorkManager _unitOfWorkManager;
@ -24,6 +26,8 @@ public class UpdateAggregateRootWhenNavigationChanges_Tests : EntityFrameworkCor
{ {
_entityWithForeignKeyOnlyRepository = GetRequiredService<IRepository<AppEntityWithForeignKeyOnly, Guid>>(); _entityWithForeignKeyOnlyRepository = GetRequiredService<IRepository<AppEntityWithForeignKeyOnly, Guid>>();
_childRepository = GetRequiredService<IRepository<AppEntityWithForeignKeyOnlyChild, Guid>>(); _childRepository = GetRequiredService<IRepository<AppEntityWithForeignKeyOnlyChild, Guid>>();
_ownerRepository = GetRequiredService<IRepository<AppEntityWithForeignKeyOnlyOwner, Guid>>();
_entityChildRepository = GetRequiredService<IRepository<AppEntityWithForeignKeyOnlyEntityChild, Guid>>();
_entityWithNavigationsRepository = GetRequiredService<IRepository<AppEntityWithNavigations, Guid>>(); _entityWithNavigationsRepository = GetRequiredService<IRepository<AppEntityWithNavigations, Guid>>();
_entityWithNavigationsForeignRepository = GetRequiredService<IRepository<AppEntityWithNavigationsForeign, Guid>>(); _entityWithNavigationsForeignRepository = GetRequiredService<IRepository<AppEntityWithNavigationsForeign, Guid>>();
_unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>(); _unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>();
@ -63,6 +67,95 @@ public class UpdateAggregateRootWhenNavigationChanges_Tests : EntityFrameworkCor
(await _entityWithForeignKeyOnlyRepository.GetAsync(principalId)).ConcurrencyStamp.ShouldBe(concurrencyStamp); (await _entityWithForeignKeyOnlyRepository.GetAsync(principalId)).ConcurrencyStamp.ShouldBe(concurrencyStamp);
} }
[Fact]
public async Task Should_Not_Update_Principal_Entity_Without_Navigation_Property_On_Update_And_Delete()
{
var principalId = Guid.NewGuid();
var childId = Guid.NewGuid();
await WithUnitOfWorkAsync(async () =>
{
await _entityWithForeignKeyOnlyRepository.InsertAsync(
new AppEntityWithForeignKeyOnly(principalId, "Principal"));
await _childRepository.InsertAsync(
new AppEntityWithForeignKeyOnlyChild(childId, principalId, "Child"));
});
var concurrencyStamp = (await _entityWithForeignKeyOnlyRepository.GetAsync(principalId)).ConcurrencyStamp;
await WithUnitOfWorkAsync(async () =>
{
await _entityWithForeignKeyOnlyRepository.GetAsync(principalId);
var child = await _childRepository.GetAsync(childId);
child.Name = "Child-Updated";
await _childRepository.UpdateAsync(child);
});
(await _entityWithForeignKeyOnlyRepository.GetAsync(principalId)).ConcurrencyStamp.ShouldBe(concurrencyStamp);
await WithUnitOfWorkAsync(async () =>
{
await _entityWithForeignKeyOnlyRepository.GetAsync(principalId);
await _childRepository.DeleteAsync(childId);
});
(await _entityWithForeignKeyOnlyRepository.GetAsync(principalId)).ConcurrencyStamp.ShouldBe(concurrencyStamp);
}
[Fact]
public async Task Should_Update_The_Owner_But_Not_The_Referenced_Aggregate_Root_Of_A_Child_Entity()
{
var ownerId = Guid.NewGuid();
var referencedId = Guid.NewGuid();
await WithUnitOfWorkAsync(async () =>
{
await _ownerRepository.InsertAsync(new AppEntityWithForeignKeyOnlyOwner(ownerId, "Owner"));
await _entityWithForeignKeyOnlyRepository.InsertAsync(
new AppEntityWithForeignKeyOnly(referencedId, "Referenced"));
});
var ownerStamp = (await _ownerRepository.GetAsync(ownerId)).ConcurrencyStamp;
var referencedStamp = (await _entityWithForeignKeyOnlyRepository.GetAsync(referencedId)).ConcurrencyStamp;
await WithUnitOfWorkAsync(async () =>
{
await _ownerRepository.GetAsync(ownerId);
await _entityWithForeignKeyOnlyRepository.GetAsync(referencedId);
await _entityChildRepository.InsertAsync(
new AppEntityWithForeignKeyOnlyEntityChild(Guid.NewGuid(), ownerId, referencedId, "Child"));
});
(await _ownerRepository.GetAsync(ownerId)).ConcurrencyStamp.ShouldNotBe(ownerStamp);
(await _entityWithForeignKeyOnlyRepository.GetAsync(referencedId)).ConcurrencyStamp.ShouldBe(referencedStamp);
}
[Fact]
public async Task Should_Update_Aggregate_Root_When_Owned_Entity_Changes()
{
var entityId = Guid.NewGuid();
await WithUnitOfWorkAsync(async () =>
{
await _entityWithNavigationsRepository.InsertAsync(
new AppEntityWithNavigations(entityId, "Entity"));
});
var concurrencyStamp = (await _entityWithNavigationsRepository.GetAsync(entityId)).ConcurrencyStamp;
await WithUnitOfWorkAsync(async () =>
{
var entity = await _entityWithNavigationsRepository.GetAsync(entityId);
entity.AppEntityWithValueObjectAddress = new AppEntityWithValueObjectAddress("Turkey");
await _entityWithNavigationsRepository.UpdateAsync(entity);
});
(await _entityWithNavigationsRepository.GetAsync(entityId)).ConcurrencyStamp.ShouldNotBe(concurrencyStamp);
}
[Fact] [Fact]
public async Task Should_Update_Aggregate_Root_When_Navigation_Changes_By_Default() public async Task Should_Update_Aggregate_Root_When_Navigation_Changes_By_Default()
{ {

17
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs

@ -42,6 +42,10 @@ public class TestMigrationsDbContext : AbpDbContext<TestMigrationsDbContext>
public DbSet<AppEntityWithForeignKeyOnlyChild> AppEntityWithForeignKeyOnlyChild { get; set; } public DbSet<AppEntityWithForeignKeyOnlyChild> AppEntityWithForeignKeyOnlyChild { get; set; }
public DbSet<AppEntityWithForeignKeyOnlyOwner> AppEntityWithForeignKeyOnlyOwner { get; set; }
public DbSet<AppEntityWithForeignKeyOnlyEntityChild> AppEntityWithForeignKeyOnlyEntityChild { get; set; }
public DbSet<Blog> Blogs { get; set; } public DbSet<Blog> Blogs { get; set; }
public DbSet<BlogPost> BlogPosts { get; set; } public DbSet<BlogPost> BlogPosts { get; set; }
@ -178,6 +182,19 @@ public class TestMigrationsDbContext : AbpDbContext<TestMigrationsDbContext>
b.HasOne<AppEntityWithForeignKeyOnly>().WithMany().HasForeignKey(x => x.AppEntityWithForeignKeyOnlyId); b.HasOne<AppEntityWithForeignKeyOnly>().WithMany().HasForeignKey(x => x.AppEntityWithForeignKeyOnlyId);
}); });
modelBuilder.Entity<AppEntityWithForeignKeyOnlyOwner>(b =>
{
b.ConfigureByConvention();
b.HasMany(x => x.Children).WithOne().HasForeignKey(x => x.OwnerId);
});
modelBuilder.Entity<AppEntityWithForeignKeyOnlyEntityChild>(b =>
{
b.ConfigureByConvention();
// The owner has a navigation, the referenced aggregate root has not.
b.HasOne<AppEntityWithForeignKeyOnly>().WithMany().HasForeignKey(x => x.AppEntityWithForeignKeyOnlyId);
});
modelBuilder.Entity<Blog>(b => modelBuilder.Entity<Blog>(b =>
{ {
b.ConfigureByConvention(); b.ConfigureByConvention();

17
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs

@ -50,6 +50,10 @@ public class TestAppDbContext : AbpDbContext<TestAppDbContext>, IThirdDbContext,
public DbSet<AppEntityWithForeignKeyOnlyChild> AppEntityWithForeignKeyOnlyChild { get; set; } public DbSet<AppEntityWithForeignKeyOnlyChild> AppEntityWithForeignKeyOnlyChild { get; set; }
public DbSet<AppEntityWithForeignKeyOnlyOwner> AppEntityWithForeignKeyOnlyOwner { get; set; }
public DbSet<AppEntityWithForeignKeyOnlyEntityChild> AppEntityWithForeignKeyOnlyEntityChild { get; set; }
public DbSet<Blog> Blogs { get; set; } public DbSet<Blog> Blogs { get; set; }
public DbSet<BlogPost> BlogPosts { get; set; } public DbSet<BlogPost> BlogPosts { get; set; }
@ -177,6 +181,19 @@ public class TestAppDbContext : AbpDbContext<TestAppDbContext>, IThirdDbContext,
b.HasOne<AppEntityWithForeignKeyOnly>().WithMany().HasForeignKey(x => x.AppEntityWithForeignKeyOnlyId); b.HasOne<AppEntityWithForeignKeyOnly>().WithMany().HasForeignKey(x => x.AppEntityWithForeignKeyOnlyId);
}); });
modelBuilder.Entity<AppEntityWithForeignKeyOnlyOwner>(b =>
{
b.ConfigureByConvention();
b.HasMany(x => x.Children).WithOne().HasForeignKey(x => x.OwnerId);
});
modelBuilder.Entity<AppEntityWithForeignKeyOnlyEntityChild>(b =>
{
b.ConfigureByConvention();
// The owner has a navigation, the referenced aggregate root has not.
b.HasOne<AppEntityWithForeignKeyOnly>().WithMany().HasForeignKey(x => x.AppEntityWithForeignKeyOnlyId);
});
modelBuilder.Entity<AppEntityWithNavigationChildOneToOne>(b => modelBuilder.Entity<AppEntityWithNavigationChildOneToOne>(b =>
{ {
b.ConfigureByConvention(); b.ConfigureByConvention();

44
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/AppEntityWithNavigations.cs

@ -160,3 +160,47 @@ public class AppEntityWithForeignKeyOnlyChild : AggregateRoot<Guid>
public string Name { get; set; } public string Name { get; set; }
} }
public class AppEntityWithForeignKeyOnlyOwner : AggregateRoot<Guid>
{
protected AppEntityWithForeignKeyOnlyOwner()
{
}
public AppEntityWithForeignKeyOnlyOwner(Guid id, string name)
: base(id)
{
Name = name;
}
public string Name { get; set; }
public virtual List<AppEntityWithForeignKeyOnlyEntityChild> Children { get; set; }
}
/// <summary>
/// Belongs to the <see cref="AppEntityWithForeignKeyOnlyOwner"/> aggregate,
/// but references the <see cref="AppEntityWithForeignKeyOnly"/> aggregate root with a foreign key only.
/// </summary>
public class AppEntityWithForeignKeyOnlyEntityChild : Entity<Guid>
{
protected AppEntityWithForeignKeyOnlyEntityChild()
{
}
public AppEntityWithForeignKeyOnlyEntityChild(Guid id, Guid ownerId, Guid appEntityWithForeignKeyOnlyId, string name)
: base(id)
{
OwnerId = ownerId;
AppEntityWithForeignKeyOnlyId = appEntityWithForeignKeyOnlyId;
Name = name;
}
public Guid OwnerId { get; set; }
public Guid AppEntityWithForeignKeyOnlyId { get; set; }
public string Name { get; set; }
}

Loading…
Cancel
Save