mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-10-15 01:54:43 +00:00
Migrate Auth/Brewery/Location repositories to pure Dapper; rename Timer to RowVersion (#237)
* Integrate Spectre.Console into seed application, use async data loading * Replace stored-procedure repositories with Dapper-based repositories Removes the USP_* stored procedures for Auth, Location, and Brewery data access in favour of services built with Dapper. Adds a new Features.Locations slice and optimistic concurrency support for the Brewery slice. * Add new documentation for Dapper migration/database schema * Update FluentAssertions to most recent open source ver * Update XML doc comment in backend projects * Modify brewery location dto to include denormalized data * - Updated column names from 'Timer' to 'RowVersion' in schema.sql for - Introduced new BeerPost entity and updated BreweryPost and BreweryPostLocation entities to use 'RowVersion' for concurrency. - Modified UserAccount, UserCredential, UserVerification, City, StateProvince, and Country entities to use 'RowVersion' instead of 'Timer'. - Updated tests and command handlers to reflect changes in concurrency token from 'Timer' to 'RowVersion'. - Adjusted BreweryDto and BreweryDtoMapper to include 'RowVersion' and updated mapping logic accordingly. - Ensured all repository methods and interfaces are aligned with the new concurrency handling approach. * updates * Add BeerStyle entity and related properties; refactor BreweryDto to remove BeerPosts * Fix Api.Specs test failures: stale Timer column refs and missing test.user fixture * Remove repository tests, usages of registration dto used in repo * archive old stored procs/functions * update stale docs * Add instructions for generating cryptographically secure base64 secrets on macOS/Linux and Windows
This commit is contained in:
@@ -21,6 +21,7 @@ public class UpdateBreweryHandlerTests
|
||||
{
|
||||
UpdateBreweryCommand command = new(
|
||||
Guid.NewGuid(),
|
||||
[0x01, 0x02],
|
||||
Guid.NewGuid(),
|
||||
"Renamed",
|
||||
"New description",
|
||||
@@ -31,7 +32,7 @@ public class UpdateBreweryHandlerTests
|
||||
_repoMock
|
||||
.Setup(r => r.UpdateAsync(It.IsAny<BreweryPost>()))
|
||||
.Callback<BreweryPost>(b => persisted = b)
|
||||
.Returns(Task.CompletedTask);
|
||||
.ReturnsAsync(() => persisted!);
|
||||
|
||||
DateTime before = DateTime.UtcNow;
|
||||
await _handler.Handle(command, CancellationToken.None);
|
||||
@@ -42,6 +43,7 @@ public class UpdateBreweryHandlerTests
|
||||
persisted.PostedById.Should().Be(command.PostedById);
|
||||
persisted.BreweryName.Should().Be("Renamed");
|
||||
persisted.Description.Should().Be("New description");
|
||||
persisted.RowVersion.Should().Equal(command.RowVersion);
|
||||
persisted.UpdatedAt.Should().NotBeNull();
|
||||
persisted.UpdatedAt!.Value.Should().BeOnOrAfter(before).And.BeOnOrBefore(after);
|
||||
}
|
||||
@@ -51,6 +53,7 @@ public class UpdateBreweryHandlerTests
|
||||
{
|
||||
UpdateBreweryCommand command = new(
|
||||
Guid.NewGuid(),
|
||||
[0x01, 0x02],
|
||||
Guid.NewGuid(),
|
||||
"Name",
|
||||
"Description",
|
||||
@@ -61,7 +64,7 @@ public class UpdateBreweryHandlerTests
|
||||
_repoMock
|
||||
.Setup(r => r.UpdateAsync(It.IsAny<BreweryPost>()))
|
||||
.Callback<BreweryPost>(b => persisted = b)
|
||||
.Returns(Task.CompletedTask);
|
||||
.ReturnsAsync(() => persisted!);
|
||||
|
||||
await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
@@ -81,6 +84,7 @@ public class UpdateBreweryHandlerTests
|
||||
);
|
||||
UpdateBreweryCommand command = new(
|
||||
Guid.NewGuid(),
|
||||
[0x01, 0x02],
|
||||
Guid.NewGuid(),
|
||||
"Name",
|
||||
"Description",
|
||||
@@ -91,7 +95,7 @@ public class UpdateBreweryHandlerTests
|
||||
_repoMock
|
||||
.Setup(r => r.UpdateAsync(It.IsAny<BreweryPost>()))
|
||||
.Callback<BreweryPost>(b => persisted = b)
|
||||
.Returns(Task.CompletedTask);
|
||||
.ReturnsAsync(() => persisted!);
|
||||
|
||||
await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
<PackageReference Include="Moq" Version="4.20.72" />
|
||||
<PackageReference Include="FluentAssertions" Version="6.9.0" />
|
||||
<PackageReference Include="DbMocker" Version="1.26.0" />
|
||||
<PackageReference Include="FluentAssertions" Version="7.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
using Apps72.Dev.Data.DbMocker;
|
||||
using Domain.Entities;
|
||||
using Features.Breweries.Repository;
|
||||
using FluentAssertions;
|
||||
|
||||
namespace Features.Breweries.Tests.Repository;
|
||||
|
||||
public class BreweryRepositoryTests
|
||||
{
|
||||
private static BreweryRepository CreateRepo(MockDbConnection conn)
|
||||
{
|
||||
return new BreweryRepository(new TestConnectionFactory(conn));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetByIdAsync_ReturnsBrewery_WhenExists()
|
||||
{
|
||||
Guid breweryId = Guid.NewGuid();
|
||||
MockDbConnection conn = new();
|
||||
|
||||
// Repository calls the stored procedure
|
||||
const string getByIdSql = "USP_GetBreweryById";
|
||||
|
||||
Guid locationId = Guid.NewGuid();
|
||||
|
||||
conn.Mocks.When(cmd => cmd.CommandText == getByIdSql)
|
||||
.ReturnsTable(
|
||||
MockTable
|
||||
.WithColumns(
|
||||
("BreweryPostId", typeof(Guid)),
|
||||
("PostedById", typeof(Guid)),
|
||||
("BreweryName", typeof(string)),
|
||||
("Description", typeof(string)),
|
||||
("CreatedAt", typeof(DateTime)),
|
||||
("UpdatedAt", typeof(DateTime?)),
|
||||
("Timer", typeof(byte[])),
|
||||
("BreweryPostLocationId", typeof(Guid)),
|
||||
("CityId", typeof(Guid)),
|
||||
("AddressLine1", typeof(string)),
|
||||
("AddressLine2", typeof(string)),
|
||||
("PostalCode", typeof(string)),
|
||||
("Coordinates", typeof(byte[]))
|
||||
)
|
||||
.AddRow(
|
||||
breweryId,
|
||||
Guid.NewGuid(),
|
||||
"Test Brewery",
|
||||
"A test brewery description",
|
||||
DateTime.UtcNow,
|
||||
null,
|
||||
null,
|
||||
locationId,
|
||||
Guid.NewGuid(),
|
||||
"123 Main St",
|
||||
null,
|
||||
"12345",
|
||||
null
|
||||
)
|
||||
);
|
||||
|
||||
BreweryRepository repo = CreateRepo(conn);
|
||||
BreweryPost? result = await repo.GetByIdAsync(breweryId);
|
||||
result.Should().NotBeNull();
|
||||
result!.BreweryPostId.Should().Be(breweryId);
|
||||
result.Location.Should().NotBeNull();
|
||||
result.Location!.BreweryPostLocationId.Should().Be(locationId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetByIdAsync_ReturnsNull_WhenNotExists()
|
||||
{
|
||||
MockDbConnection conn = new();
|
||||
conn.Mocks.When(cmd => cmd.CommandText == "USP_GetBreweryById")
|
||||
.ReturnsTable(MockTable.Empty());
|
||||
BreweryRepository repo = CreateRepo(conn);
|
||||
BreweryPost? result = await repo.GetByIdAsync(Guid.NewGuid());
|
||||
result.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateAsync_ExecutesSuccessfully()
|
||||
{
|
||||
MockDbConnection conn = new();
|
||||
conn.Mocks.When(cmd => cmd.CommandText == "USP_CreateBrewery").ReturnsScalar(1);
|
||||
BreweryRepository repo = CreateRepo(conn);
|
||||
BreweryPost brewery = new()
|
||||
{
|
||||
BreweryPostId = Guid.NewGuid(),
|
||||
PostedById = Guid.NewGuid(),
|
||||
BreweryName = "Test Brewery",
|
||||
Description = "A test brewery description",
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
Location = new BreweryPostLocation
|
||||
{
|
||||
BreweryPostLocationId = Guid.NewGuid(),
|
||||
CityId = Guid.NewGuid(),
|
||||
AddressLine1 = "123 Main St",
|
||||
PostalCode = "12345",
|
||||
Coordinates = [0x00, 0x01],
|
||||
},
|
||||
};
|
||||
|
||||
// Should not throw
|
||||
Func<Task> act = async () => await repo.CreateAsync(brewery);
|
||||
await act.Should().NotThrowAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System.Data.Common;
|
||||
using Infrastructure.Sql;
|
||||
|
||||
namespace Features.Breweries.Tests.Repository;
|
||||
|
||||
internal class TestConnectionFactory(DbConnection conn) : ISqlConnectionFactory
|
||||
{
|
||||
private readonly DbConnection _conn = conn;
|
||||
|
||||
public DbConnection CreateConnection()
|
||||
{
|
||||
return _conn;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user