Fluent Assertions – Working with Exceptions
When writing automated tests, verifying that a certain piece of code throws the expected exception is just as important as verifying positive outcomes. Fluent Assertions in C# makes exception testing more readable, expressive, and less error-prone compared to traditional Assert.Throws syntax.
Why Test for Exceptions?
Exception testing ensures that your application behaves correctly in edge cases and error scenarios. For example:
- When invalid input should trigger an exception
- When certain operations are not allowed
- When dependencies fail and your code must handle it gracefully
Traditional xUnit Exception Testing
[Fact]
public void Divide_By_Zero_Should_Throw_Exception()
{
Assert.Throws<DivideByZeroException>(() => Calculator.Divide(10, 0));
}
This works fine, but it’s not as expressive and doesn’t allow detailed inspection of the exception message in a clean way.
Exception Testing with Fluent Assertions
Fluent Assertions makes this much easier and more expressive:
[Fact]
public void Divide_By_Zero_Should_Throw_Exception()
{
Action act = () => Calculator.Divide(10, 0);
act.Should()
.Throw<DivideByZeroException>()
.WithMessage("*divide by zero*");
}
Key Benefits:
- Readable chain of assertions
- Ability to verify exception type and message
- Supports wildcards in messages (
*text*)
Capturing the Exception for Further Assertions
Sometimes, you may need to inspect additional properties of the exception:
[Fact]
public void Invalid_Operation_Should_Contain_Extra_Details()
{
Action act = () => OrderService.ProcessOrder(null);
var exception = act.Should()
.Throw<InvalidOperationException>()
.Which;
exception.Data["OrderId"].Should().BeNull();
}
Async Exception Testing
For asynchronous methods, Fluent Assertions provides an await act.Should().ThrowAsync<T>() syntax:
[Fact]
public async Task Async_Method_Should_Throw_Exception()
{
Func<Task> act = async () => await UserService.CreateUserAsync(null);
await act.Should()
.ThrowAsync<ArgumentNullException>()
.WithMessage("*username*");
}
Best Practices for Exception Testing
- Test both exception type and message when applicable
- Use wildcard matching for messages to avoid brittle tests
- For async methods, always use
ThrowAsync - Keep tests focused on one scenario per method
๐ฃ I’d Love Your Feedback
Was this helpful? Have scenarios you want covered (e.g., dictionaries, sets, or deep-object comparisons)? Share your suggestions, and I’ll explore them next.
๐ Stay connected and follow HGDevHub for more micro tools, automation scripts, and tech walkthroughs:
- ๐ฆ Follow on X (Twitter)
- ✍️ Follow on Medium
- ๐️ Explore tools on Gumroad
- ๐ฅ Join the Reddit space (Coming Soon)
๐ฉ Stay Tuned
More automation scripts and micro-tools coming soon. Follow HGDevHub for fresh tools that save time and spark ideas.
Comments
Post a Comment