An AwesomeAssertions extension library
for CSharpFunctionalExtensions, providing expressive,
type-safe, and discoverable assertions for Result, Result<T>, Result<T, E>, Maybe<T>, and UnitResult<E> types. Latest version available here:
- Strongly-typed assertions for all CSharpFunctionalExtensions result types.
- Source-generated extension methods for primitive, collection, and enum types, making assertions more discoverable and concise.
- Seamless integration with AwesomeAssertions.
Add the NuGet package to your test project:
dotnet add package CSharpFunctionalExtensions.AwesomeAssertionsThe real power of this library comes from the source-generated extension methods. These methods are context-aware and provide direct access to the underlying value or error, returning the most appropriate AwesomeAssertions/FluentAssertions assertion type for the value. This makes your assertions more concise, type-safe, and discoverable.
using FluentAssertions;
using CSharpFunctionalExtensions;
Result<string> result = Result.Success("hello");
result.SuccessShould().Be("hello");
result.SuccessShould().StartWith("he"); // Direct access to the StringAssertions (Or any other type of assertions based on the value)Result<string> result = Result.Failure("fail!");
result.FailureShould().Be("fail!");
result.FailureShould().Contain("fail"); // Direct access to the StringAssertions (Or any other type of assertions based on the error type)
result.FailureShould().NotBeNullOrWhiteSpace();Maybe<string> maybe = Maybe<string>.From("hello");
maybe.ValueShould().StartWith("he");Result<int[]> result = Result.Success(new[] { 1, 2, 3 });
result.SuccessShould().Contain(2);
result.SuccessShould().HaveCount(3).And.OnlyContain(x => x > 0);
result.SuccessShould().NotBeEmpty().And.BeEquivalentTo([1, 2, 3]);enum Status { Ok, Error }
Result<Status> result = Result.Success(Status.Ok);
result.SuccessShould<Status, int>().Be(Status.Ok); // The generic type parameters are a due to a limitation with generic type inference in C#.Result<int, string> result = Result.Success<int, string>(5);
result.SuccessShould().Be(5);
Result<int, string> failed = Result.Failure<int, string>("bad");
failed.FailureShould().Be("bad");UnitResult<string> result = UnitResult.Failure("error");
result.FailureShould().Be("error");You can also use the classic assertion methods if you prefer, or if you need to assert on enums with custom logic:
You can use the classic assertion methods for all result types. Note that with classic assertions, you need to use
.Which to access the value for further assertions:
using FluentAssertions;
using CSharpFunctionalExtensions;
Result result = Result.Success();
result.Should().Succeed();
Result<int> resultT = Result.Success(42);
resultT.Should().SucceedWith(42);
Result<int, string> resultTE = Result.Success<int, string>(99);
resultTE.Should().SucceedWith(99);
Maybe<string> maybe = Maybe<string>.From("hello");
maybe.Should().HaveSomeValue().Which.Should().StartWith("he"); // .Which required for further assertions
Result<int[]> resultArr = Result.Success(new[] { 1, 2, 3 });
resultArr.Should().Succeed().Which.Should().Contain(2);
resultArr.Should().Succeed().Which.Should().HaveCount(3).And.OnlyContain(x => x > 0);
resultArr.Should().Succeed().Which.Should().NotBeEmpty().And.BeEquivalentTo([1, 2, 3]);
// Yeah, the generated extension methods are more concise!
Result<string> failed = Result.Failure<int>("fail!");
failed.Should().Fail().Which.Should().Be("fail!");- Discoverability: Just type
.after your result/maybe and see the available assertion methods in IntelliSense. - Type Safety: The extension returns the most specific assertion type (e.g.,
NumericAssertions<int>,GenericCollectionAssertions<T>,EnumAssertions<TEnum>, etc.). - Less Boilerplate: No need to chain
.Should().Succeed().Whichjust call the generated method and assert directly.
The library uses a source generator to create these extension methods for all supported types.
If you want to see or extend the generated code, check the [GeneratePrimitiveExtensions] attribute usage in the
codebase.