Files
db-subclass-to-dto/tests/BeforeAfter.Tests/AfterPersistenceTests.cs
T
mostalive 53586d33a4 identity read-back: FromOrderData/FromClientData + DbContext.LoadOrder/LoadClient
Plain field-copy materialization so the persistence round-trip closes.
When OrderLines arrive, FromOrderData becomes the one-line reconstruction
(row description + total become a single line) — the hinge Exercise 2
pivots on.

yak: orderdata-read-back-identity-version-j9ew [order-data-mapping]
2026-09-16 22:17:28 +01:00

149 lines
5.0 KiB
C#

using After;
namespace BeforeAfter.Tests;
/// <summary>
/// The after <see cref="DbContext"/> stores data-only persistence records
/// (<see cref="ClientData"/> / <see cref="OrderData"/>), never domain objects:
/// <see cref="DbContext"/>'s <c>Save</c> maps domain state into a row —
/// inserting on the first save, refreshing in place on later ones — and the
/// stored graph is flattened to ids.
/// </summary>
public class AfterPersistenceTests
{
[Fact]
public void Save_maps_domain_state_into_data_records()
{
var db = new DbContext();
var client = new Client { Name = "Acme" };
var order = new Order { Description = "one", TotalInCents = 15000 };
client.Orders.Add(order);
db.Save(client);
db.Save(order);
var clientRow = Assert.Single(db.Clients);
Assert.Equal(client.Id, clientRow.Id);
Assert.Equal("Acme", clientRow.Name);
var orderRow = Assert.Single(db.Orders);
Assert.Equal(order.Id, orderRow.Id);
Assert.Equal("one", orderRow.Description);
Assert.Equal(15000, orderRow.TotalInCents);
Assert.Equal(client.Id, orderRow.ClientId); // the graph is flattened to a key
}
[Fact]
public void An_order_without_client_stores_an_empty_client_id()
{
var db = new DbContext();
var order = new Order { Description = "orphan" };
db.Save(order);
Assert.Equal(Guid.Empty, Assert.Single(db.Orders).ClientId);
}
[Fact]
public void Saving_again_refreshes_the_row_instead_of_duplicating_it()
{
var db = new DbContext();
var client = new Client { Name = "Acme" };
var order = new Order { Description = "one" };
client.Orders.Add(order);
db.Save(client);
db.Save(order);
order.Description = "one (edited)";
order.TotalInCents = 9900;
client.Name = "Acme GmbH";
db.Save(order);
db.Save(client);
// One row per saved object, refreshed with the *current* state:
var orderRow = Assert.Single(db.Orders);
Assert.Equal(order.Id, orderRow.Id);
Assert.Equal("one (edited)", orderRow.Description);
Assert.Equal(9900, orderRow.TotalInCents);
Assert.Equal(client.Id, orderRow.ClientId);
var clientRow = Assert.Single(db.Clients);
Assert.Equal("Acme GmbH", clientRow.Name);
}
[Fact]
public void Rows_are_reachable_through_Set_and_Find()
{
var db = new DbContext();
var client = new Client { Name = "Acme" };
var order = new Order { Description = "one" };
client.Orders.Add(order);
db.Save(client);
db.Save(order);
Assert.Single(db.Set<ClientData>());
Assert.Single(db.Set<OrderData>());
var found = db.Find<OrderData>(row => row.Description == "one");
Assert.Equal(order.Id, found!.Id);
Assert.Null(db.Find<OrderData>(row => row.Description == "no such order"));
}
// ---------------------------------------------------------------------
// Read-back: LoadOrder / LoadClient reassemble domain objects from the
// stored rows (identity round-trip for now — OrderLines come later).
// ---------------------------------------------------------------------
[Fact]
public void Loading_an_order_restores_its_state_and_its_client()
{
var db = new DbContext();
var client = new Client { Name = "Acme" };
var order = new Order { Description = "one", TotalInCents = 150_00 };
client.Orders.Add(order);
db.Save(client);
db.Save(order);
var loaded = db.LoadOrder(order.Id);
Assert.NotNull(loaded);
Assert.Equal(order.Id, loaded!.Id);
Assert.Equal("one", loaded.Description);
Assert.Equal(150_00, loaded.TotalInCents);
// The graph is reassembled: the loaded order knows its client again,
// and the client's collection holds the loaded order.
Assert.NotNull(loaded.Client);
Assert.Equal("Acme", loaded.Client!.Name);
Assert.Same(loaded, Assert.Single(loaded.Client.Orders));
}
[Fact]
public void Loading_a_client_restores_it_with_all_of_its_orders()
{
var db = new DbContext();
var client = new Client { Name = "Acme" };
client.Orders.Add(new Order { Description = "one", TotalInCents = 150_00 });
client.Orders.Add(new Order { Description = "two", TotalInCents = 250_00 });
db.Save(client);
db.Save(client.Orders[0]);
db.Save(client.Orders[1]);
var loaded = db.LoadClient(client.Id);
Assert.NotNull(loaded);
Assert.Equal("Acme", loaded!.Name);
Assert.Equal(2, loaded.Orders.Count);
Assert.All(loaded.Orders, o => Assert.Same(loaded, o.Client));
}
[Fact]
public void Loading_an_unknown_id_returns_null()
{
var db = new DbContext();
Assert.Null(db.LoadOrder(Guid.NewGuid()));
Assert.Null(db.LoadClient(Guid.NewGuid()));
}
}