Init
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Prefab.Catalog.Api.Data;
|
||||
using Prefab.Catalog.Domain.Entities;
|
||||
using Prefab.Catalog.Domain.Services;
|
||||
using Prefab.Handler;
|
||||
using Shouldly;
|
||||
|
||||
namespace Prefab.Tests.Unit.Modules.Catalog.Data;
|
||||
|
||||
public sealed class ProductConcurrencyShould : IAsyncLifetime, IDisposable
|
||||
{
|
||||
private readonly HandlerContextAccessor _accessor = new();
|
||||
private readonly DbContextOptions<AppDb> _options;
|
||||
|
||||
public ProductConcurrencyShould()
|
||||
{
|
||||
var databaseName = Guid.NewGuid().ToString();
|
||||
_options = new DbContextOptionsBuilder<AppDb>()
|
||||
.UseInMemoryDatabase(databaseName)
|
||||
.Options;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ThrowWhenSavingWithStaleRowVersion()
|
||||
{
|
||||
var checker = new PermissiveUniqueChecker();
|
||||
|
||||
await using (var seedContext = CreateContext())
|
||||
{
|
||||
var product = await Product.CreateModel("Demo Model", "demo-model", "Demo", checker, CancellationToken.None);
|
||||
product.SetBasePrice(10m);
|
||||
product.RowVersion = Guid.NewGuid().ToByteArray();
|
||||
|
||||
seedContext.Products.Add(product);
|
||||
await seedContext.SaveChangesAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
await using var writerOne = CreateContext();
|
||||
await using var writerTwo = CreateContext();
|
||||
|
||||
var first = await writerOne.Products.FirstAsync(CancellationToken.None);
|
||||
var second = await writerTwo.Products.FirstAsync(CancellationToken.None);
|
||||
|
||||
first.SetBasePrice(12m);
|
||||
writerOne.Entry(first).Property(p => p.RowVersion).CurrentValue = Guid.NewGuid().ToByteArray();
|
||||
await writerOne.SaveChangesAsync(CancellationToken.None);
|
||||
|
||||
second.SetBasePrice(14m);
|
||||
|
||||
await Should.ThrowAsync<DbUpdateConcurrencyException>(
|
||||
() => writerTwo.SaveChangesAsync(CancellationToken.None));
|
||||
}
|
||||
|
||||
public ValueTask InitializeAsync() => ValueTask.CompletedTask;
|
||||
|
||||
private AppDb CreateContext() => new(_options, _accessor);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
|
||||
|
||||
private sealed class PermissiveUniqueChecker : IUniqueChecker
|
||||
{
|
||||
public Task<bool> CategoryNameIsUnique(string name, CancellationToken cancellationToken = default) => Task.FromResult(true);
|
||||
|
||||
public Task<bool> ProductModelNameIsUnique(string name, CancellationToken cancellationToken = default) => Task.FromResult(true);
|
||||
|
||||
public Task<bool> ProductSlugIsUnique(string? slug, CancellationToken cancellationToken = default) => Task.FromResult(true);
|
||||
|
||||
public Task<bool> ProductSkuIsUnique(string sku, CancellationToken cancellationToken = default) => Task.FromResult(true);
|
||||
|
||||
public Task<bool> OptionCodeIsUniqueForProduct(Guid productId, string code, CancellationToken cancellationToken = default) => Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user