Skip to main content

Anatomy of an expectation

Every expectation starts with Expect.That(subject), continues with what you expect and is awaited:

string title = "Let It Be";

await Expect.That(title).StartsWith("Abbey").Because("it is the album title");

A failure throws the exception of your test framework, with a message that reads like a sentence. The expectation above fails with:

Failure message
Expected that title
starts with "Abbey", because it is the album title,
but it was "Let It Be", which differs at index 0:
↓ (actual)
"Let It Be"
"Abbey"
↑ (expected prefix)
  • The first line names the subject with the expression you passed to Expect.That.
  • The second line states the expectation, followed by the reason from Because(…).
  • The line starting with "but" describes what was found instead.

Evaluated when awaited​

Every expectation is lazy: it is only evaluated when it is awaited. An expectation that is not awaited never fails, so only the second line can fail the test:

Expect.That(result).IsTrue(); // never evaluated
await Expect.That(result).IsTrue(); // evaluated, fails when result is false

The analyzer rule aweXpect0001 reports an expectation that is neither awaited nor verified, and aweXpect0005 reports an expectation in an async void method or lambda, whose failure would be thrown after the test has completed.

Awaiting an expectation also returns the value it verified, see combining.

When you cannot await​

ref struct values can't be used in an async method. For a property of such a value, or of a span on a target framework that can't pass spans to Expect.That, verify the expectation synchronously, so that the test method itself can remain synchronous:

using aweXpect.Synchronous;

ReadOnlySpan<char> title = "Let It Be".AsSpan();

Expect.That(title.Length).IsEqualTo(9).VerifySynchronously();
// or alternatively:
Synchronously.Verify(Expect.That(title.Length).IsEqualTo(9));
warning

Only use this where awaiting is impossible: it blocks the thread until the expectation is evaluated.