Accepting an order gives the service several things to get right. The caller needs the accepted outcome. The database needs the complete order. Fulfillment needs enough information to act. The customer needs the correct communication.
About the examples: Meridian Ordering is a private training reference project. The inline listings illustrate the techniques; the full C# and Python repositories are not currently public.
This article follows one complete Meridian acceptance test that verifies those obligations through the public ordering operation. The feature’s requirements, criteria, functional and non-functional obligations, and correct scenarios and expectations are established first. The test then supplies execution evidence for this scenario. Its result contributes to confidence to release when the required suite is green.
The scenario we are verifying
AC-01 describes an existing active customer ordering three Widgets and two Gadgets. Using the specification’s example prices, the line totals are $59.97 and $499.00, and the order total is $558.97. The order is Placed because that total is at or below the $10,000.00 review threshold.
The implementation of the test reads catalog products during Arrange and derives its expectations from their actual prices. The specification’s arithmetic is the rule. Its worked example is a checkable instance of that rule.
The order uses several parts of the system:
- The application code validates the request and applies the ordering rules.
- The database supplies catalog prices and records the order and its lines.
- The message broker carries the asynchronous notification to fulfillment.
- The email gateway submits the customer’s confirmation. Meridian captures this request in the test; it deliberately has no separate running email service.
The complete outcome includes the caller’s reference, total, and status; the recorded order and lines; one fulfillment notification with the required content; and one confirmation request for the address on file. The obligation map connects those requirements to the observations and comparisons below.
Read the whole test before its helpers
The complete method below comes from Meridian. Its phase comments use
/// Arrange, /// Act, and /// Assert for this article; its executable
statements are unchanged. Arrange establishes inputs and expectations, Act invokes
the operation, and Assert gathers actual results and compares them with those
expectations. Its imports, containing
class, reserved identifiers, initialization, and teardown are in the
complete source file.
The explanations below describe the supporting helpers and show selected listings.
public async Task PlaceOrder_WhenActiveCustomerPlacesValidOrder_ThenOrderIsRecordedFulfillmentNotifiedAndConfirmationEmailed()
{
/// Arrange - Given an active customer, two catalog products read from the store
// (randomized - the seeded catalog is the single source of truth for product
// data), and listeners on both channels. Quantities mirror the AC-01 example.
var customerRecord = ArrangedCustomers.CreateArrangedCustomer(_expectedOrderPlacementIdentifiers.CustomerId);
int firstLineQuantity = 3;
int secondLineQuantity = 2;
// The price cap makes AC-01's implicit constraint explicit: whatever the draw,
// the derived total stays at or under the BR-6 threshold, so the order is Placed.
decimal maximumUnitPrice = DataGenerators.GetMaximumUnitPriceWithoutTriggeringReview(AcceptanceTestConstants.HeldForReviewThresholdTotal, firstLineQuantity + secondLineQuantity);
var catalogProducts = DataManagerForTest.GetRandomCatalogProducts(
2, maximumUnitPrice: maximumUnitPrice);
var firstCatalogProduct = catalogProducts[0];
var secondCatalogProduct = catalogProducts[1];
var orderPlacementRequest = RequestBuilders.OrderPlacementRequestBuilder
.Set(request => request.OrderReference, _expectedOrderPlacementIdentifiers.OrderReference)
.Set(request => request.CustomerId, customerRecord.CustomerId)
.Set(request => request.OrderPlacementLineItems,
[
new OrderPlacementLineItem(sku: LetterCasing.SwapCase(firstCatalogProduct.Sku), quantity: firstLineQuantity),
new OrderPlacementLineItem(sku: LetterCasing.SwapCase(secondCatalogProduct.Sku), quantity: secondLineQuantity),
])
.Build();
// The expected outcome is written ONCE, as the complete PlacedOrder: BR-5's
// own arithmetic (quantity x catalog unit price) applied to the prices just
// read. (The spec's worked example, 3 x Widget + 2 x Gadget = $558.97, stays
// in the spec document as the example to check by hand.) Every other expected
// value - the caller's response, the recorded order lines, the wire-shaped
// fulfillment lines, and the composed email - is built from this PlacedOrder
// by CreateFrom, so the test does not repeat them.
decimal expectedFirstLineTotal = firstCatalogProduct.UnitPrice * firstLineQuantity;
decimal expectedSecondLineTotal = secondCatalogProduct.UnitPrice * secondLineQuantity;
var expectedPlacedOrder = new PlacedOrder(
OrderReference: orderPlacementRequest.OrderReference,
CustomerId: customerRecord.CustomerId,
OrderPlacementStatus: OrderPlacementStatus.Placed,
OrderTotal: expectedFirstLineTotal + expectedSecondLineTotal,
PlacedAtUtc: DateTime.UtcNow,
PlacedOrderLines:
[
new PlacedOrderLine(
sku: firstCatalogProduct.Sku,
productName: firstCatalogProduct.ProductName,
quantity: firstLineQuantity,
unitPrice: firstCatalogProduct.UnitPrice,
lineTotal: expectedFirstLineTotal),
new PlacedOrderLine(
sku: secondCatalogProduct.Sku,
productName: secondCatalogProduct.ProductName,
quantity: secondLineQuantity,
unitPrice: secondCatalogProduct.UnitPrice,
lineTotal: expectedSecondLineTotal),
]);
var expectedSuccessfulOrderPlacement = ExpectedSuccessfulOrderPlacement.CreateFrom(
expectedPlacedOrder,
new CustomerContact(CustomerId: customerRecord.CustomerId, EmailAddress: customerRecord.Email));
// One call creates the DomainFacade and its paired test doubles, interconnected
// through the testing service locator; this test needs the email Test Mediator.
var (domainFacadeInstance, testMediatorEmailService, _) = DomainFacadeFactory.CreateDomainFacade();
await using var domainFacade = domainFacadeInstance;
await using var subscriberFulfillmentNotifications =
await BrokerSubscriptions.SubscribeToFulfillmentNotificationsForTestAsync();
var expectedPlacementWindowStartUtc = DateTime.UtcNow;
/// Act - When the customer places an order with two line items
OrderPlacementResult actualOrderPlacementResult = await domainFacade.PlaceOrderAsync(orderPlacementRequest);
/// Assert - gather what actually happened, visibly: read the recorded order
// back from the store, receive the fulfillment message from the broker, and
// listen through the quiet window for any extra message
var actualRecordedOrder = DataManagerForTest.GetRecordedOrder(orderPlacementRequest.OrderReference);
var actualFulfillmentNotificationPayload = await BrokerSubscriptions.ReceiveMessageForOrderAsync(
subscriberFulfillmentNotifications, orderPlacementRequest.OrderReference);
var actualExtraFulfillmentNotificationPayload = await BrokerSubscriptions.TryReceiveMessageForOrderAsync(
subscriberFulfillmentNotifications, orderPlacementRequest.OrderReference);
var actualPlacementWindowEndUtc = DateTime.UtcNow;
/// Assert - every AC-01 obligation, reported together: the caller's response,
// the recorded order and its two lines carrying catalog prices, fulfillment
// notified exactly once with everything needed to act, and exactly one
// confirmation email with the composed content to the address on file
var actualSuccessfulOrderPlacement = new ActualSuccessfulOrderPlacement(
actualOrderPlacementResult,
actualRecordedOrder,
actualFulfillmentNotificationPayload,
actualExtraFulfillmentNotificationPayload,
testMediatorEmailService.CapturedEmailRequests.ToArray(),
testMediatorEmailService.CapturedRequestPaths.ToArray());
AsserterSuccessfulOrderPlacement.AssertAllAc01ObligationsAreMet(
expectedSuccessfulOrderPlacement: expectedSuccessfulOrderPlacement,
expectedPlacementWindowStartUtc: expectedPlacementWindowStartUtc,
actualPlacementWindowEndUtc: actualPlacementWindowEndUtc,
actualSuccessfulOrderPlacement: actualSuccessfulOrderPlacement);
}
The test has three visible jobs: establish the scenario and its expected outcome, invoke the public operation, and gather and verify what happened. Each helper exists to support one of those jobs.
Own the identities and the customer record
The containing class reserves a customer identifier and an order reference before arrangement starts. Its asynchronous teardown deletes the records owned by those identifiers even if arrangement, execution, or assertions fail.
ArrangedCustomers creates the customer and inserts it into the real database. The production customer check therefore encounters an actual active customer. The test keeps the arranged contact information so its email expectation uses the address on file.
/// Arrange: create records owned by this run.
private readonly ExpectedOrderPlacementIdentifiers _expectedOrderPlacementIdentifiers =
DataGenerators.CreateExpectedOrderPlacementIdentifiers();
var customerRecord = ArrangedCustomers.CreateArrangedCustomer(
_expectedOrderPlacementIdentifiers.CustomerId);
The random customer and order identifiers keep concurrent runs from changing or removing one another’s records. A fixed customer shared by developers or parallel CI jobs would make this scenario depend on what those other runs were doing.
Active status, valid quantities, and the order’s relation to the review threshold establish the business scenario. Random identities keep its records separate.
Select data that preserves the named scenario
The test asks for two catalog products without replacement. Their permitted maximum price is calculated from the review threshold and the sum of the quantities. If both selected prices are at or below that cap, three units of one product plus two of the other remain at or below the threshold.
DataManagerForTest reads the catalog, filters prices when a cap is supplied, checks that enough eligible products exist, samples them, and returns them in SKU order. That order matches the database’s line ordering for positional comparison.
The cap prevents a random selection from turning this Placed scenario into a Held for Review scenario. Sampling without replacement prevents accidental duplicate products. With the supplied seed, the eligible set can constrain which products are selected; randomness does not promise a different product set on every run.
The request uses swapped letter casing for the selected SKUs. Expected recorded and outbound values retain canonical uppercase identity. This lets the same scenario verify that input casing does not change which product was ordered.
The request builders and immutable ModelBuilder keep the request arrangement readable. Explicit Set calls expose the identifiers and line items that determine this scenario.
Here is the catalog selection and request arrangement from the complete test:
/// Arrange: choose valid products and quantities.
int firstLineQuantity = 3;
int secondLineQuantity = 2;
decimal maximumUnitPrice = DataGenerators.GetMaximumUnitPriceWithoutTriggeringReview(AcceptanceTestConstants.HeldForReviewThresholdTotal, firstLineQuantity + secondLineQuantity);
var catalogProducts = DataManagerForTest.GetRandomCatalogProducts(
2, maximumUnitPrice: maximumUnitPrice);
var firstCatalogProduct = catalogProducts[0];
var secondCatalogProduct = catalogProducts[1];
var orderPlacementRequest = RequestBuilders.OrderPlacementRequestBuilder
.Set(request => request.OrderReference, _expectedOrderPlacementIdentifiers.OrderReference)
.Set(request => request.CustomerId, customerRecord.CustomerId)
.Set(request => request.OrderPlacementLineItems,
[
new OrderPlacementLineItem(sku: LetterCasing.SwapCase(firstCatalogProduct.Sku), quantity: firstLineQuantity),
new OrderPlacementLineItem(sku: LetterCasing.SwapCase(secondCatalogProduct.Sku), quantity: secondLineQuantity),
])
.Build();
The request supplies SKU and quantity. It supplies no price. During the operation, the production code reads each product record in the database and uses its catalog price. The earlier test-side read gives us the price for our expectation.
Establish the expected order once
The expected line totals come from the selected catalog prices and BR-5’s formula: quantity multiplied by unit price. Their sum establishes the expected order total. The expected PlacedOrder carries the complete line values and the required status.
The expected order is built before the operation runs:
/// Arrange: calculate expected values from the catalog and business rule.
decimal expectedFirstLineTotal = firstCatalogProduct.UnitPrice * firstLineQuantity;
decimal expectedSecondLineTotal = secondCatalogProduct.UnitPrice * secondLineQuantity;
var expectedPlacedOrder = new PlacedOrder(
OrderReference: orderPlacementRequest.OrderReference,
CustomerId: customerRecord.CustomerId,
OrderPlacementStatus: OrderPlacementStatus.Placed,
OrderTotal: expectedFirstLineTotal + expectedSecondLineTotal,
PlacedAtUtc: DateTime.UtcNow,
PlacedOrderLines:
[
new PlacedOrderLine(
sku: firstCatalogProduct.Sku,
productName: firstCatalogProduct.ProductName,
quantity: firstLineQuantity,
unitPrice: firstCatalogProduct.UnitPrice,
lineTotal: expectedFirstLineTotal),
new PlacedOrderLine(
sku: secondCatalogProduct.Sku,
productName: secondCatalogProduct.ProductName,
quantity: secondLineQuantity,
unitPrice: secondCatalogProduct.UnitPrice,
lineTotal: expectedSecondLineTotal),
]);
var expectedSuccessfulOrderPlacement = ExpectedSuccessfulOrderPlacement.CreateFrom(
expectedPlacedOrder,
new CustomerContact(CustomerId: customerRecord.CustomerId, EmailAddress: customerRecord.Email));
ExpectedSuccessfulOrderPlacement.CreateFrom then creates the required representations of that expected order: the caller result, recorded lines, fulfillment lines, wire-formatted amounts, and confirmation email. This avoids retyping the same expected facts in several places.
The complete expected-model factory shows each conversion. Amounts on the fulfillment wire use invariant two-decimal formatting. The email expectation uses the production composer, whose independent class tests verify the content it produces. Those tests are the condition for borrowing that composer as an oracle.
The expected placement time in the arranged model is not an exact prediction of the database clock. The stored timestamp has a separate bounded-time check, and its propagation into fulfillment has an exact-value check.
Arrange the operation and fulfillment observation
The factory gives the test its public facade and the email capture object used by that same facade. The test also subscribes to fulfillment before placing the order, so it can observe the message when the operation publishes it:
/// Arrange: create the operation and its observation objects.
var (domainFacadeInstance, testMediatorEmailService, _) = DomainFacadeFactory.CreateDomainFacade();
await using var domainFacade = domainFacadeInstance;
await using var subscriberFulfillmentNotifications =
await BrokerSubscriptions.SubscribeToFulfillmentNotificationsForTestAsync();
The database and broker are real. The test uses the order reference to identify its own fulfillment message. BrokerSubscriptions provides the subscription and correlation helpers. We will explain the email capture separately after following the assertions.
Invoke the public operation visibly
The Act is the call to DomainFacade.PlaceOrderAsync. Someone reading or debugging the scenario can find the operation being tested immediately.
/// Act: invoke the public ordering operation.
var expectedPlacementWindowStartUtc = DateTime.UtcNow;
OrderPlacementResult actualOrderPlacementResult =
await domainFacade.PlaceOrderAsync(orderPlacementRequest);
The facade delegates to ManagerOrdering. The manager validates the request, canonicalizes SKU identity, asks the production data manager to place the order, and performs the new order’s required actions.
The data manager calls the SQL procedures. The ordinary placement procedure checks customer and catalog facts, calculates totals, and writes the order, lines, and initial action states in one transaction. It returns the recorded order data that the production path uses for outbound work.
After commit, fulfillment is published and confirmation is submitted when required. Successful actions acquire completion evidence. Business-required failure handling preserves the accepted order and pending obligations when a defined operational action cannot complete. The source listing includes those policies; later articles will follow their distinct scenarios in detail.
This walkthrough describes the internals to teach the implementation. The acceptance test’s contract remains the public operation and its observable effects. It does not assert that a particular internal class or method was called.
Gather independent evidence
After the Act, we gather what the operation produced:
- The returned result comes from the completed public operation.
- The stored order and its lines come from a new database query using this run’s order reference, independently of the production data manager.
- The fulfillment payload comes from receiving this order’s broker message.
- The extra-message observation comes from listening for another message for the same order during the quiet window.
- The email requests and paths come from the capture object used by this facade.
Here are the database and broker reads:
/// Assert: gather the actual database and broker results.
var actualRecordedOrder = DataManagerForTest.GetRecordedOrder(orderPlacementRequest.OrderReference);
var actualFulfillmentNotificationPayload = await BrokerSubscriptions.ReceiveMessageForOrderAsync(
subscriberFulfillmentNotifications, orderPlacementRequest.OrderReference);
var actualExtraFulfillmentNotificationPayload = await BrokerSubscriptions.TryReceiveMessageForOrderAsync(
subscriberFulfillmentNotifications, orderPlacementRequest.OrderReference);
var actualPlacementWindowEndUtc = DateTime.UtcNow;
The test combines those observations with the returned result and email captures:
/// Assert: compare the full expected and actual outcomes.
var actualSuccessfulOrderPlacement = new ActualSuccessfulOrderPlacement(
actualOrderPlacementResult,
actualRecordedOrder,
actualFulfillmentNotificationPayload,
actualExtraFulfillmentNotificationPayload,
testMediatorEmailService.CapturedEmailRequests.ToArray(),
testMediatorEmailService.CapturedRequestPaths.ToArray());
AsserterSuccessfulOrderPlacement.AssertAllAc01ObligationsAreMet(
expectedSuccessfulOrderPlacement: expectedSuccessfulOrderPlacement,
expectedPlacementWindowStartUtc: expectedPlacementWindowStartUtc,
actualPlacementWindowEndUtc: actualPlacementWindowEndUtc,
actualSuccessfulOrderPlacement: actualSuccessfulOrderPlacement);
These observations serve different obligations. A correct return value cannot establish that the database wrote every line. A correct database row cannot establish that fulfillment received the complete payload. A correct message cannot establish that the customer communication used the right address.
The helper that reads the order uses the expected reference as its query key. The store asserter checks customer, status, total, lines, and placement time. It does not contain a separate expected-reference parameter; the keyed readback establishes which order is being examined.
The placement window begins immediately before the operation and ends after gathering. The store comparison permits one minute of clock skew on either side. This is a bounded check that the recorded time belongs to this placement. The fulfillment comparison parses the wire timestamp and compares it with the independently read stored timestamp, verifying propagation of that recorded value.
The broker’s extra-message check uses a one-second quiet window. It establishes that no additional correlated message was observed in that window. This test does not prove absence for all future time or exactly-once delivery after crashes and later recovery. Email capture is a synchronous observation of the requests that reached the handler during this operation.
Compare every obligation and report the complete failure
The aggregate asserter calls the comparisons for all five obligation groups. It collects each returned failure report and makes one final xUnit assertion.
public static void AssertAllAc01ObligationsAreMet(
ExpectedSuccessfulOrderPlacement expectedSuccessfulOrderPlacement,
DateTime expectedPlacementWindowStartUtc,
DateTime actualPlacementWindowEndUtc,
ActualSuccessfulOrderPlacement actualSuccessfulOrderPlacement)
{
const int ObligationCount = 5;
var failedObligationReports = new List<string>();
// Obligation - the caller receives the arranged success response
string? responseReport = CompareOrderPlacementResult(
expectedSuccessfulOrderPlacement.OrderPlacementResult, actualSuccessfulOrderPlacement.OrderPlacementResult);
if (responseReport is not null)
{
failedObligationReports.Add("OBLIGATION: the caller's response\n" + responseReport);
}
// Obligation - the order and its lines are recorded with catalog prices (BR-5)
string? recordedOrderReport = AsserterOrderStore.CompareCustomerStatusTotalLinesAndPlacementTime(
expectedCustomerId: expectedSuccessfulOrderPlacement.PlacedOrder.CustomerId,
expectedOrderPlacementStatus: expectedSuccessfulOrderPlacement.PlacedOrder.OrderPlacementStatus,
expectedOrderTotal: expectedSuccessfulOrderPlacement.PlacedOrder.OrderTotal,
expectedOrderLines: expectedSuccessfulOrderPlacement.RecordedOrderLines,
expectedPlacementWindowStartUtc: expectedPlacementWindowStartUtc,
actualPlacementWindowEndUtc: actualPlacementWindowEndUtc,
actualRecordedOrder: actualSuccessfulOrderPlacement.RecordedOrder);
if (recordedOrderReport is not null)
{
failedObligationReports.Add("OBLIGATION: the recorded order\n" + recordedOrderReport);
}
// Obligation - the fulfillment message carries everything needed to act (BR-6)
string? fulfillmentContentReport = AsserterFulfillmentNotification.CompareNotification(
expectedOrderReference: expectedSuccessfulOrderPlacement.PlacedOrder.OrderReference,
expectedCustomerId: expectedSuccessfulOrderPlacement.PlacedOrder.CustomerId,
expectedFulfillmentNotificationLinePayloads: expectedSuccessfulOrderPlacement.FulfillmentNotificationLinePayloads,
expectedOrderTotal: expectedSuccessfulOrderPlacement.FulfillmentWireOrderTotal,
// The wire must carry the placement time the store recorded - a moment
// only the store knows, so the read-back recorded order is its source.
expectedPlacedAtUtc: actualSuccessfulOrderPlacement.RecordedOrder?.PlacedAtUtc,
actualFulfillmentNotificationPayload: actualSuccessfulOrderPlacement.FulfillmentNotificationPayload);
if (fulfillmentContentReport is not null)
{
failedObligationReports.Add("OBLIGATION: the fulfillment message content\n" + fulfillmentContentReport);
}
// Obligation - fulfillment is notified exactly once (BR-6)
string? extraMessageReport = AsserterMessageBroker.CompareNoMessageArrived(
actualSuccessfulOrderPlacement.ExtraFulfillmentNotificationPayload,
expectedSuccessfulOrderPlacement.PlacedOrder.OrderReference,
"AC-01: fulfillment is notified exactly once");
if (extraMessageReport is not null)
{
failedObligationReports.Add("OBLIGATION: fulfillment notified exactly once\n" + extraMessageReport);
}
// Obligation - exactly one confirmation email with the composed content (BR-8)
string? confirmationEmailReport = AsserterConfirmationEmail.CompareExactlyOneEmailSent(
expectedSuccessfulOrderPlacement.ConfirmationEmailMessage, actualSuccessfulOrderPlacement.CapturedEmailRequests, actualSuccessfulOrderPlacement.EmailRequestPaths);
if (confirmationEmailReport is not null)
{
failedObligationReports.Add("OBLIGATION: the confirmation email\n" + confirmationEmailReport);
}
Assert.True(
failedObligationReports.Count == 0,
$"\nSUCCESSFUL ORDER PLACEMENT ASSERTION FAILED\n" +
$"{failedObligationReports.Count} of {ObligationCount} obligations failed. Each report follows.\n\n" +
string.Join("\n\n----------------------------------------\n\n", failedObligationReports));
}
The comparisons are pure checks over the expected and actual data supplied by the test. They perform no database or broker reads. Gathering remains visible in the scenario, while detailed comparison remains reusable.
AsserterOrderStore compares the customer, status, total, placement window, and complete ordered line records. Record equality includes SKU, product name, quantity, unit price, and line total. Sequence equality includes the line count and order.
AsserterFulfillmentNotification compares reference, customer, lines, total, and placement time. AsserterConfirmationEmail compares request and path counts, the /emails path, recipient, subject, body, and order reference. AsserterMessageBroker checks the unexpected-message observation.
Accumulation makes a failed outcome easier to understand. A wrong total can appear in the caller result, stored order, fulfillment notification, and email. The report preserves the failed comparisons that are available instead of stopping at the first mismatch. A gathering failure, such as a missing required database row, can still stop the test before the aggregate comparison is reached.
The assertion-report tests deliberately supply wrong or missing observations and check the diagnostic reports. The reporting mechanism earns its own verification.
Email capture: protect recipients and observe the submitted confirmation
We need to check the customer’s address, subject, and body without sending test messages to real customers. We also need access to those values after the order operation has finished.
Meridian is a teaching application. It has no separate running email service. Its Test Mediator records the outgoing request and returns an arranged HTTP 200 response for this scenario. It forwards nothing to an email provider. The captured requests and paths are therefore the email actuals used by the asserter above.
DomainFacadeFactory creates the facade and its mediator together. The production configuration provider, managers, validators, data manager, publisher, composers, and email gateway remain in the operation’s path. The mediator’s HttpMessageHandler captures at the point where the gateway’s request would leave for the email service. The gateway still constructs the request and interprets the response.
With a stable real provider and a controlled test inbox, the arrangement can also verify delivery:
- Capture the original request, preserving its intended customer recipient, subject, body, and order reference.
- Replace the recipient in the forwarded request with a unique, routable test address. Keep the original capture unchanged.
- Forward the request and let the real provider send the message.
- Compare the original capture with the expected customer and confirmation.
- Read this run’s message from the controlled inbox within a defined timeout. Compare the delivered subject and body, and verify the controlled recipient.
The capture verifies whom the application intended to contact. The inbox verifies what arrived after redirection. Parallel runs need distinct addresses or aliases that the test environment can receive, plus correlation to each run’s order. Meridian implements request capture; the real delivery arrangement described here is the production approach, and requires its own provider and inbox support.
The Test Mediator and Transport Spy article shows the same example’s capture method, paired factory, failure scripts, and response-body observations. It also explains the separate mediator-and-spies shape and the combined shape Meridian uses. Those implementation shapes can support different delivery arrangements.
Change the scenario and follow the changed obligations
The second scenario in the same complete test class orders three Turbine Blades. It reads the live price and guards that the total exceeds the review threshold.
The caller receives Held for Review. The order and lines are still recorded. Fulfillment must remain absent, its action state is NotRequired, and the email must acknowledge review without promising fulfillment. The held-order asserter compares those obligations together.
Customer Registration supplies another useful example: a successful operation returns nothing, yet it must record every supplied value correctly. Its full and minimal registration tests and accepted-registration asserter show how observable state provides the outcome to verify.
Recorded execution of the examples
These listings come from Meridian revision 501e097f66b884615f517c5252d1ab719709f421. They belong to its .NET 10 solution; the inline listings are excerpts from that project. The full solution remains private. The following command records how its selected scenarios were executed.
With SQL Server and RabbitMQ running and test configuration in place, the disposable-database runner can select the two ordering scenarios:
dotnet run --project setup/MeridianOrdering.Setup -- run-tests --project tests/MeridianOrdering.Tests/MeridianOrdering.Tests.csproj --filter "FullyQualifiedName~TestPlaceOrderExpectedPaths"
The runner hydrates a fresh database and removes it after the run. It keeps this execution separate from an existing shared test database.
The broader verification for these examples ran all selected Place Order tests and both production composers’ class tests against real SQL Server and RabbitMQ: 77 test cases passed, with no failures or skips. A separate run of the assertion report tests passed all 18 cases. Those receipts establish the selected execution results; scenario and expectation review establishes what the results mean.
This one scenario shows why the arrangement and assertion work is substantial. The test supplies evidence for the accepted order across its required effects. Once the feature’s correct scenarios and expectations cover its established requirements, green results across the required suite give the team confidence to go to production.
