diff --git a/TUnit.Assertions/Core/Assertion.cs b/TUnit.Assertions/Core/Assertion.cs index 1b9e06afc7..5e047a409f 100644 --- a/TUnit.Assertions/Core/Assertion.cs +++ b/TUnit.Assertions/Core/Assertion.cs @@ -137,30 +137,42 @@ public Assertion Because(string message) } // Normal single-assertion execution (never delegates to wrapper) - var (value, exception) = await Context.GetAsync(); + var contextResult = await Context.GetAsync(); + var result = await CreateMetadataAndCheckAsync(contextResult.Value, contextResult.Exception); + + if (!result.IsPassed) + { + ThrowOrAccumulateFailure(result); + } + + return contextResult.Value; + } + + // Create EvaluationMetadata in a separate scope to avoid creating additional + // DateTimeOffset fields in the state machine + private Task CreateMetadataAndCheckAsync(TValue? value, Exception? exception) + { var (startTime, endTime) = Context.GetTiming(); var metadata = new EvaluationMetadata(value, exception, startTime, endTime); - var result = await CheckAsync(metadata); + return CheckAsync(metadata); + } - if (!result.IsPassed) + private void ThrowOrAccumulateFailure(AssertionResult result) + { + var assertionException = CreateException(result); + var currentScope = AssertionScope.GetCurrentAssertionScope(); + + if (currentScope != null) { - var assertionException = CreateException(result); - var currentScope = AssertionScope.GetCurrentAssertionScope(); - - if (currentScope != null) - { - // Within Assert.Multiple - accumulate exception instead of throwing - currentScope.AddException((AssertionException)assertionException); - } - else - { - // No scope - throw immediately - throw assertionException; - } + // Within Assert.Multiple - accumulate exception instead of throwing + currentScope.AddException((AssertionException)assertionException); + } + else + { + // No scope - throw immediately + throw assertionException; } - - return value; } ///