Welcome to Shouldly Documentation
A modern, assertion framework for .NET that focuses on clear error messages and fluent assertions
Introduction
What is Shouldly?
Shouldly is a modern assertion framework for .NET that reimagines how test assertions should work. Unlike traditional assertion libraries, Shouldly focuses on providing exceptionally readable test code and human-friendly error messages that clearly show what went wrong. Its expressive syntax lets developers write assertions that read like natural language, making tests more intuitive and maintainable.
Traditional vs Shouldly Approach
Traditional Assertion
Assert.That(contestant.Points, Is.EqualTo(1337));
Error message:
Shouldly Assertion
contestant.Points.ShouldBe(1337);
Error message:
Why use Shouldly?
Shouldly dramatically improves the testing experience by:
- Providing highly descriptive error messages that include the actual code being tested
- Using natural language assertions that improve readability and maintainability
- Making tests more approachable for developers of all experience levels
- Reducing the cognitive load needed to understand test failures
- Seamlessly integrating with existing test frameworks like NUnit, xUnit, and MSTest
Key Features of Shouldly
Human-Readable Assertions
Write tests that read like sentences with methods like ShouldBe(), ShouldContain(), and ShouldThrow()
Exceptional Error Messages
Get detailed failure messages that include the actual code expression being tested
Fluent Syntax
Chain assertion methods naturally for complex verifications
Strongly-Typed
Enjoy full IntelliSense support and compile-time checking
Customizable
Extend with your own custom assertions when needed
Performance
Optimized for speed with minimal overhead compared to traditional assertions
Getting Started with Shouldly
Installation
Shouldly can be installed via NuGet package manager:
Install-Package Shouldly
nuget install Shouldly
dotnet add package Shouldly
Basic Usage Examples
using Shouldly;
using NUnit.Framework;
[Test]
public void BasicAssertionExamples()
{
// Basic equality
var myValue = 42;
myValue.ShouldBe(42);
// String operations
string name = "John Smith";
name.ShouldContain("Smith");
name.ShouldStartWith("John");
name.ShouldNotBeNullOrEmpty();
// Collection assertions
var myList = new[] { new Person { Name = "John" }, new Person { Name = "Jane" } };
myList.ShouldContain(x => x.Name == "John");
myList.ShouldNotBeEmpty();
myList.Length.ShouldBe(2);
// Exception testing
Should.Throw(() => ThrowIfNegative(-1));
}
Advanced Usage
Shouldly provides numerous advanced assertions for more complex scenarios:
Working with Collections
// Collection assertions
var numbers = new[] { 1, 2, 3, 4, 5 };
numbers.ShouldContain(3);
numbers.ShouldNotContain(10);
numbers.ShouldBeSubsetOf(new[] { 1, 2, 3, 4, 5, 6, 7 });
numbers.ShouldAllBe(x => x > 0);
numbers.ShouldContain(x => x % 2 == 0);
Verifying Exceptions
// Exception assertions
Should.Throw(() =>
ThrowException("Invalid argument"))
.Message.ShouldContain("Invalid");
Should.NotThrow(() => DoSomethingThatShouldNotThrow());
// Exception with specific message
Should.Throw(() =>
ThrowException("Parameter cannot be null"),
"Parameter cannot be null");
Working with Approximate Values
// Approximate comparisons for floating-point
double value = 0.1 + 0.2; // 0.30000000000000004 in most systems
value.ShouldBe(0.3, 0.00001);
// Date assertions within a time range
DateTime now = DateTime.Now;
now.ShouldBeInRange(DateTime.Now.AddMinutes(-1), DateTime.Now.AddMinutes(1));
Real-World Examples
Unit Testing Example
This example demonstrates testing a shopping cart calculation service:
[Test]
public void CalculateTotal_WithValidItems_ReturnsCorrectTotal()
{
// Arrange
var cart = new ShoppingCart();
cart.AddItem(new CartItem("Book", 10.99m, 2));
cart.AddItem(new CartItem("Pen", 1.99m, 5));
var service = new CartCalculationService();
// Act
decimal total = service.CalculateTotal(cart);
// Assert
total.ShouldBe(31.93m);
cart.ItemCount.ShouldBe(2);
cart.TotalItems.ShouldBe(7);
}
TDD Workflow Example
Using Shouldly in a Test-Driven Development approach:
// Step 1: Write failing test
[Test]
public void ValidateEmail_WithValidEmail_ReturnsTrue()
{
// Arrange
var validator = new EmailValidator();
string email = "user@example.com";
// Act
bool isValid = validator.ValidateEmail(email);
// Assert
isValid.ShouldBeTrue();
}
// Step 2: Implement the simplest code to pass
public class EmailValidator
{
public bool ValidateEmail(string email)
{
return email.Contains("@") && email.Contains(".");
}
}
// Step 3: Add more tests for edge cases
[Test]
public void ValidateEmail_WithMissingAtSymbol_ReturnsFalse()
{
// Arrange
var validator = new EmailValidator();
string email = "userexample.com";
// Act
bool isValid = validator.ValidateEmail(email);
// Assert
isValid.ShouldBeFalse();
}
Integration Testing Example
Using Shouldly to verify database operations:
[Test]
public async Task CreateUser_WithValidData_ShouldPersistToDatabase()
{
// Arrange
var repository = new UserRepository(_dbContext);
var user = new User
{
Username = "johndoe",
Email = "john@example.com",
FirstName = "John",
LastName = "Doe"
};
// Act
await repository.CreateAsync(user);
var savedUser = await repository.GetByIdAsync(user.Id);
// Assert
savedUser.ShouldNotBeNull();
savedUser.Id.ShouldNotBe(0);
savedUser.Username.ShouldBe("johndoe");
savedUser.Email.ShouldBe("john@example.com");
// Verify database was updated
_dbContext.Users.Count().ShouldBe(1);
}
Resources for Shouldly
Official Documentation
Comprehensive guides and API reference for using Shouldly effectively in your testing projects.
View DocumentationGitHub Repository
The official source code repository where you can explore the codebase, report issues, or contribute to the project.
View on GitHubTesting .NET Core with Shouldly
A detailed guide on implementing Shouldly in modern .NET Core applications with practical examples.
Read GuideShouldly vs Fluent Assertions
An in-depth analysis comparing Shouldly with its main competitor, helping you choose the right assertion framework for your project.
Read ComparisonVideo Tutorials
Getting Started with Shouldly
30:15 • 45K views
Advanced Testing Techniques
22:45 • 32K views
TDD with Shouldly
45:10 • 56K views
Community and Support
Discussion Forum
Connect with other Shouldly users to ask questions and share best practices.
Join the DiscussionStack Overflow
Browse through community questions and answers related to Shouldly implementation.
View QuestionsContributing
Guidelines for developers interested in contributing to the Shouldly project.
Learn HowWhat Developers Say
"Shouldly transformed our testing approach. The readable error messages have made debugging so much easier for our team."
"We migrated from classic NUnit assertions to Shouldly and immediately saw an improvement in our test readability and maintainability."
"The fluent syntax and detailed error messages in Shouldly have made our TDD workflow much more efficient. Highly recommended!"
Comparison with Other Assertion Frameworks
| Framework | Syntax Style | Error Messages | Learning Curve | .NET Support | Last Update |
|---|---|---|---|---|---|
| Shouldly | Natural language | Detailed with code context | Low | Full .NET ecosystem | April 2025 |
| NUnit | Traditional | Basic | Medium | Full .NET ecosystem | March 2025 |
| xUnit | Minimalist | Basic | Medium | Full .NET ecosystem | February 2025 |
| Fluent Assertions | Fluent chains | Detailed | Medium | Full .NET ecosystem | January 2025 |
Feature Comparison
Latest Updates and News
Shouldly 4.2.1 Released
The latest point release brings performance improvements and bugfixes for async assertions.
Read Release NotesShouldly 4.2.0 Released
Major update with new assertion methods and improved error messages for collection comparisons.
Read Release NotesThe State of .NET Testing in 2025
Microsoft's developer blog covering the evolution of testing frameworks including Shouldly's growing adoption.
Read Article