TestDataBuilders: ValidOrder()/ValidClient() with explicit Build(); After tests migrated
Domain objects in After-side tests are constructed only through the builders, so the upcoming OrderLines evolution changes builder internals instead of every test. Before keeps object initializers (legacy world). yak: testdatabuilders-validordervalidclient-after-test-migration-91vl
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
using After;
|
||||
|
||||
namespace BeforeAfter.Tests.TestData;
|
||||
|
||||
/// <summary>
|
||||
/// Test data builder for a <see cref="Client"/> with its orders
|
||||
/// (TestDataBuilder pattern). <see cref="ValidClient"/> starts from a
|
||||
/// <em>fresh</em> client, exactly what <c>new Client()</c> gives.
|
||||
/// </summary>
|
||||
public sealed class ClientBuilder
|
||||
{
|
||||
private readonly Client _client = new();
|
||||
|
||||
/// <summary>A valid, fresh client — the neutral starting point for tests.</summary>
|
||||
public static ClientBuilder ValidClient() => new();
|
||||
|
||||
public ClientBuilder WithId(Guid id)
|
||||
{
|
||||
_client.Id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ClientBuilder WithName(string name)
|
||||
{
|
||||
_client.Name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Adds an order to the client (navigation fix-up wires the back-reference).</summary>
|
||||
public ClientBuilder WithOrder(Order order)
|
||||
{
|
||||
_client.Orders.Add(order);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Builds the given builder and adds its order — chaining sugar for <c>.WithOrder(builder.Build())</c>.</summary>
|
||||
public ClientBuilder WithOrder(OrderBuilder order) => WithOrder(order.Build());
|
||||
|
||||
public Client Build() => _client;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using After;
|
||||
|
||||
namespace BeforeAfter.Tests.TestData;
|
||||
|
||||
/// <summary>
|
||||
/// Test data builder for an <see cref="Order"/> (TestDataBuilder pattern).
|
||||
/// <see cref="ValidOrder"/> starts from a <em>fresh</em> order —
|
||||
/// <see cref="Guid.Empty"/> id, empty description, zero total, exactly what
|
||||
/// <c>new Order()</c> gives — and every <c>With...</c> returns the builder for
|
||||
/// chaining; <see cref="Build"/> hands back the order.
|
||||
///
|
||||
/// This class is the only place tests touch an order's *construction*: when
|
||||
/// the domain evolves (e.g. OrderLines making the total computed), only these
|
||||
/// internals change and the tests keep reading the same.
|
||||
/// </summary>
|
||||
public sealed class OrderBuilder
|
||||
{
|
||||
private readonly Order _order = new();
|
||||
|
||||
/// <summary>A valid, fresh order — the neutral starting point for tests.</summary>
|
||||
public static OrderBuilder ValidOrder() => new();
|
||||
|
||||
public OrderBuilder WithId(Guid id)
|
||||
{
|
||||
_order.Id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OrderBuilder WithDescription(string description)
|
||||
{
|
||||
_order.Description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the total in cents (<c>150_00</c> = €150.00). How the requested
|
||||
/// total is realised inside the order is an implementation detail that may
|
||||
/// change as the domain evolves; this API stays.
|
||||
/// </summary>
|
||||
public OrderBuilder WithTotal(int totalInCents)
|
||||
{
|
||||
_order.TotalInCents = totalInCents;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Order Build() => _order;
|
||||
}
|
||||
Reference in New Issue
Block a user