Skip to content

Commit cd54483

Browse files
committed
Update README with Expectation.From lambda-based API
1 parent 544f540 commit cd54483

File tree

1 file changed

+31
-22
lines changed

1 file changed

+31
-22
lines changed

README.md

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -272,38 +272,47 @@ Assert(await ThrowsAsync<InvalidOperationException>(() =>
272272

273273
### Custom Expectations
274274

275-
Create reusable expectations by inheriting from `Expectation` and returning an `EvaluationResult`.
276-
277-
Recommended convention for external/custom expectations:
278-
- Suffix the type with `Expectation` (e.g., `IsEvenExpectation`)
279-
- For unary expectations, prefer a static factory method so call sites can use `using static` (e.g., `Assert(IsEven(4))`)
280-
- For expectations that take a primary value and additional parameters, prefer extension methods for fluent call sites (e.g., `Assert(actual.IsEquivalentTo(expected))`)
275+
Create reusable expectations using `Expectation.From()` - a lambda-based factory that eliminates boilerplate:
281276

282277
```csharp
283-
sealed class IsEvenExpectation(int value) : Expectation
278+
public static class NumberExtensions
284279
{
285-
public override EvaluationResult Evaluate(ExpectationContext context) =>
286-
value % 2 == 0
287-
? ExpectationResults.Pass(context.Expression)
288-
: ExpectationResults.Fail(context.Expression, $"Expected even, got {value}");
280+
public static Expectation IsEven(this int value) =>
281+
Expectation.From(
282+
() => value % 2 == 0,
283+
() => [$"Expected even number, got {value}"]
284+
);
285+
286+
public static Expectation IsBetween(this int value, int min, int max) =>
287+
Expectation.From(
288+
() => value >= min && value <= max,
289+
() => [$"Expected {value} to be between {min} and {max}"]
290+
);
289291
}
290292

291-
static class Expectations
292-
{
293-
public static IsEvenExpectation IsEven(int value) => new(value);
294-
}
293+
Assert(4.IsEven());
294+
Assert(!5.IsEven());
295+
Assert(5.IsBetween(1, 10));
296+
```
295297

296-
using static Expectations;
298+
**How it works:**
299+
- First lambda: predicate that returns `true` if expectation passes
300+
- Second lambda: failure message factory (only called on failure, returns `string[]` for multiple diagnostic lines)
301+
- Expression text is injected automatically by the framework
297302

298-
Assert(IsEven(4));
299-
Assert(!IsEven(5));
303+
For **complex expectations** with substantial internal logic (algorithms, external library integration), you can still inherit from `Expectation`:
300304

301-
static class ExpectationExtensions
305+
```csharp
306+
sealed class IsEquivalentToExpectation<T>(T actual, T expected) : Expectation
302307
{
303-
public static IsEvenExpectation IsEven(this int value) => new(value);
308+
public override EvaluationResult Evaluate(ExpectationContext context)
309+
{
310+
// Complex comparison logic using Compare-Net-Objects...
311+
return isEqual
312+
? ExpectationResults.Pass(context.Expression)
313+
: ExpectationResults.Fail(context.Expression, differences);
314+
}
304315
}
305-
306-
Assert(4.IsEven() & !5.IsEven());
307316
```
308317

309318
### Custom Error Messages

0 commit comments

Comments
 (0)