Benday.Common.Testing 2.2.1

dotnet add package Benday.Common.Testing --version 2.2.1
                    
NuGet\Install-Package Benday.Common.Testing -Version 2.2.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Benday.Common.Testing" Version="2.2.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Benday.Common.Testing" Version="2.2.1" />
                    
Directory.Packages.props
<PackageReference Include="Benday.Common.Testing" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Benday.Common.Testing --version 2.2.1
                    
#r "nuget: Benday.Common.Testing, 2.2.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Benday.Common.Testing@2.2.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Benday.Common.Testing&version=2.2.1
                    
Install as a Cake Addin
#tool nuget:?package=Benday.Common.Testing&version=2.2.1
                    
Install as a Cake Tool

Benday.Common.Testing

A comprehensive testing library for .NET that streamlines unit testing with XUnit and Moq, featuring a powerful assertion framework with fluent syntax and descriptive error messages.

About

Written by Benjamin Day Pluralsight Author | Microsoft MVP | Scrum.org Professional Scrum Trainer https://www.benday.com https://www.slidespeaker.ai info@benday.com YouTube: https://www.youtube.com/@_benday

Key Features

1. Comprehensive Assertion Framework

The library provides a complete assertion framework that addresses XUnit's lack of descriptive failure messages. All assertions support optional custom messages for better debugging.

Static Assertion Classes
  • AssertThat - Core assertions for general testing

    • Equality checks (AreEqual, AreNotEqual)
    • Null checks (IsNull, IsNotNull)
    • Boolean assertions (IsTrue, IsFalse)
    • Type checks (IsOfType, IsNotOfType)
    • Reference equality (AreSame, AreNotSame)
    • Exception testing (Throws, DoesNotThrow)
  • AssertThatString - String-specific assertions

    • Null/empty checks (IsNullOrEmpty, IsNotNullOrEmpty, IsNullOrWhiteSpace)
    • String comparison (StartsWith, EndsWith, Contains)
    • Pattern matching (Matches with regex support)
    • Length validation (HasLength)
    • Case-insensitive comparisons
  • AssertThatCollection - Collection assertions

    • Empty checks (IsEmpty, IsNotEmpty)
    • Count validation (HasCount)
    • Element presence (Contains, DoesNotContain)
    • Subset/superset validation
    • Uniqueness checks (HasUniqueElements)
    • Element matching (AllMatch, AnyMatch)
  • AssertThatNumeric - Numeric assertions

    • Comparison operators (IsGreaterThan, IsLessThan, etc.)
    • Range validation (IsInRange, IsNotInRange)
    • Sign checks (IsPositive, IsNegative, IsZero)
    • Approximate equality for floating-point numbers
    • Special value checks (IsNotNaN, IsFinite)
Fluent Extension Methods

For more readable tests, use the fluent extension methods:

// Object assertions
actual.ShouldEqual(expected);
actual.ShouldNotBeNull();
actual.ShouldBeOfType<string>();

// String assertions
myString.ShouldNotBeNullOrEmpty()
        .ShouldStartWith("Hello")
        .ShouldContain("World");

// Collection assertions
myList.ShouldHaveCount(5)
      .ShouldContain(expectedItem)
      .ShouldHaveUniqueElements();

// Numeric assertions
myValue.ShouldBePositive()
       .ShouldBeGreaterThan(0)
       .ShouldBeLessThan(100);
Simplified Syntax (New!)

All assertion methods now support optional message parameters. You can write simpler assertions without sacrificing error message quality:

// Traditional syntax with custom message
AssertThat.AreEqual(expected, actual, "Values should match after transformation");

// Simplified syntax - still produces descriptive error messages
AssertThat.AreEqual(expected, actual);

// Fluent syntax (recommended)
actual.ShouldEqual(expected);

2. Test Base Class

  • TestClassBase - Base class for XUnit test classes
    • Provides WriteLine() method that integrates with XUnit's ITestOutputHelper
    • Simplifies console output in tests

3. Mocking Utilities

  • MockUtility - Streamlines Moq-based testing for dependency injection scenarios

    • CreateInstance<T>() - Automatically creates mocks for all constructor parameters
    • Returns MockCreationResult<T> for easy mock management
  • MockCreationResult<T> - Manages created instances and their mocks

    • Access the created instance and all generated mocks
    • Organize and verify mock interactions

Installation

Install via NuGet Package Manager:

Install-Package Benday.Common.Testing

Or via .NET CLI:

dotnet add package Benday.Common.Testing

Usage Examples

Using the Assertion Framework

public class CalculatorTests : TestClassBase
{
    public CalculatorTests(ITestOutputHelper output) : base(output)
    {
    }

    [Fact]
    public void Add_TwoNumbers_ReturnsSum()
    {
        // Arrange
        var calculator = new Calculator();

        // Act
        var result = calculator.Add(2, 3);

        // Assert using static methods
        AssertThat.AreEqual(5, result);

        // Or use fluent syntax (recommended)
        result.ShouldEqual(5)
              .ShouldBePositive()
              .ShouldBeInRange(1, 10);
    }

    [Fact]
    public void Divide_ByZero_ThrowsException()
    {
        // Arrange
        var calculator = new Calculator();
        Action divideByZero = () => calculator.Divide(10, 0);

        // Assert
        divideByZero.ShouldThrow<DivideByZeroException>();
    }
}

Using MockUtility for Dependency Injection

public class ServiceTests : TestClassBase
{
    public ServiceTests(ITestOutputHelper output) : base(output)
    {
    }

    [Fact]
    public void ProcessOrder_ValidOrder_CallsRepository()
    {
        // Arrange
        var mockUtility = new MockUtility();
        var mockResult = mockUtility.CreateInstance<OrderService>();
        var service = mockResult.Instance;

        var order = new Order { Id = 1, Total = 100.00m };

        // Setup mock behavior
        mockResult.GetMock<IOrderRepository>()
            .Setup(x => x.Save(It.IsAny<Order>()))
            .Returns(true);

        // Act
        var result = service.ProcessOrder(order);

        // Assert
        result.ShouldBeTrue();

        // Verify mock was called
        mockResult.GetMock<IOrderRepository>()
            .Verify(x => x.Save(order), Times.Once);
    }
}

Chaining Assertions for Comprehensive Tests

[Fact]
public void ValidateUserData_CompleteProfile_PassesAllValidations()
{
    // Arrange
    var userData = GetUserData();

    // Act & Assert with fluent chaining
    userData.Name
        .ShouldNotBeNullOrEmpty()
        .ShouldStartWith("John")
        .ShouldHaveLength(8);

    userData.Email
        .ShouldMatch(@"^[\w\.-]+@[\w\.-]+\.\w+$")
        .ShouldContain("@");

    userData.Permissions
        .ShouldNotBeEmpty()
        .ShouldHaveCount(3)
        .ShouldContain("read")
        .ShouldHaveUniqueElements();

    userData.Age
        .ShouldBePositive()
        .ShouldBeInRange(18, 120);
}

Why Use Benday.Common.Testing?

  1. Better Error Messages: Unlike standard XUnit assertions, our framework provides descriptive error messages that include expected and actual values, making test failures easier to diagnose.

  2. Fluent Syntax: Chain multiple assertions for more readable and maintainable tests.

  3. Comprehensive Coverage: Specialized assertions for strings, collections, numerics, and more.

  4. Simplified Mocking: MockUtility eliminates boilerplate code when testing classes with dependency injection.

  5. Optional Messages: New overloads allow simpler syntax while maintaining informative error messages.

Requirements

  • .NET 8.0, .NET 9.0, .NET 10.0, or .NET Standard 2.1
  • XUnit 2.x or higher
  • Moq 4.x or higher

Bugs? Suggestions? Contribute?

Got ideas for features you'd like to see? Found a bug? Let us know by submitting an issue. Want to contribute? Submit a pull request.

Source code

API Documentation

NuGet Package

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.2.1 295 12/17/2025
2.2.0 272 12/16/2025
2.1.0 287 11/12/2025
2.0.0 175 10/19/2025
1.5.1 216 9/30/2025
1.5.0 126 9/27/2025
1.4.0 279 8/4/2025
1.3.0 541 7/21/2025
1.2.0 358 7/20/2025
1.1.0 323 5/12/2025
1.0.0 208 4/24/2025

v2.2.1 - Metadata updates only;
v2.2 - Updated dependencies to include netstandard2.1;
v2.1 - Updated dependencies to .net 10.0;
v2.0 - Major overhaul of assertion methods so that they following a consistent naming pattern; Added new overloads to existing assertion methods to not require custom messages;
v1.5 - Added assert utility methods;
v1.4 - Changed the way MockUtility and MockCreationResult work to allow for optional mock configuration before instance creation;
v1.3 - Unpublishing fluent assertions for xUnit from this package...for now;
v1.2 - Added fluent assertions for xUnit to the package;
v1.1 - Added base class functionality for reading sample data files during tests; Removed dependency on FluentAssertions;
v1.0 - Base class for xunit tests; MockUtility for streamlining testing with Moq;