Noundry.Assertive

A fluent assertion library that makes your tests readable, intuitive, and expressive with zero runtime dependencies. Transform your test code into self-documenting specifications.

95%+
Code Coverage
Zero
Dependencies
15+
Assertion Methods
100%
Fluent API

Why Choose Noundry.Assertive?

Designed specifically for .NET developers who want readable, expressive tests without the complexity.

Fluent & Readable

Write tests that read like natural language with intuitive fluent API design and method chaining.

Zero Dependencies

No external dependencies means cleaner package references and faster build times for your test projects.

Clear Error Messages

Detailed error messages with expected vs actual values help you debug test failures quickly.

Get Started in 2 Minutes

Install Noundry.Assertive and start writing fluent, readable test assertions.

1. Installation

$ dotnet add package Noundry.Assertive

Or add to your .csproj:

<PackageReference Include="Noundry.Assertive" Version="1.0.0" />

2. Add Using Statement

using Noundry.Assertive;

3. Start Asserting

result.Assert().IsNotNull();
ProductTests.cs
using Noundry.Assertive;
using Xunit;

public class ProductTests
{
    [Fact]
    public void CreateProduct_ShouldReturnValidProduct()
    {
        // Act
        var product = new Product("Laptop", 999.99m, 10);
        
        // Assert - Fluent and readable
        product.Assert()
            .IsNotNull()
            .IsOfType<Product>()
            .Satisfies(p => p.Name == "Laptop", "Product name should match")
            .Satisfies(p => p.Price > 0, "Price should be positive");
    }
}

Complete API Reference

Comprehensive assertion methods for all your testing scenarios.

IsNotNull()

Ensures the object isn't null

result.Assert().IsNotNull()

IsNull()

Ensures the object is null

result.Assert().IsNull()

IsEqualTo(value)

Checks equality with expected value

result.Assert().IsEqualTo(42)

IsNotEqualTo(value)

Checks inequality with specified value

result.Assert().IsNotEqualTo(0)

IsOfType<T>()

Checks object's exact type

result.Assert().IsOfType<Product>()

IsNotOfType<T>()

Ensures object isn't the specified type

result.Assert().IsNotOfType<string>()

Contains(item)

Ensures collection contains the item

list.Assert().Contains(3)

DoesNotContain(item)

Ensures collection doesn't contain item

list.Assert().DoesNotContain(10)

IsEmpty<T>()

Ensures collection is empty

list.Assert().IsEmpty<int>()

IsNotEmpty<T>()

Ensures collection is not empty

list.Assert().IsNotEmpty<int>()

HasCount<T>(count)

Ensures collection has specific count

list.Assert().HasCount<int>(5)

IsInRange(min, max)

Checks if value is within range (inclusive)

age.Assert().IsInRange(18, 65)

Satisfies(predicate, message)

Validates custom conditions

user.Assert().Satisfies(u => u.IsValid)

Fails(predicate, message)

Ensures object doesn't match condition

user.Assert().Fails(u => u.IsExpired)

WithContext(context)

Adds context to error messages

user.Assert().WithContext("User validation")

Real-World Examples

Learn from practical examples showing Noundry.Assertive in action across different testing scenarios.

String & Basic Assertions

Test string values, null checks, and basic equality with fluent, readable assertions.

Fluent method chaining
Clear assertion intent
Self-documenting tests
[Fact]
public void ProcessMessage_ShouldReturnFormattedString()
{
    // Arrange
    var input = "Hello, World!";
    
    // Act
    var result = messageService.ProcessMessage(input);
    
    // Assert - Fluent and readable
    result.Assert()
        .IsNotNull()
        .IsOfType<string>()
        .IsEqualTo("HELLO, WORLD!")
        .Satisfies(s => s.Length > 5, "Should have content");
        
    // Test null scenarios
    string nullResult = null;
    nullResult.Assert().IsNull();
}

Numeric & Range Assertions

Validate numeric values, ranges, and mathematical operations with expressive assertions.

Range validation
Mathematical operations
Business rule validation
[Fact]
public void CalculateDiscount_ShouldReturnValidDiscount()
{
    // Arrange
    var originalPrice = 100m;
    var discountPercent = 20;
    
    // Act
    var discountedPrice = calculator.ApplyDiscount(originalPrice, discountPercent);
    
    // Assert - Numeric validations
    discountedPrice.Assert()
        .IsNotNull()
        .IsOfType<decimal>()
        .IsEqualTo(80m)
        .IsInRange(0m, originalPrice)
        .Satisfies(price => price < originalPrice, 
                   "Discounted price should be less than original");
}

Collection & List Testing

Test collections, lists, and arrays with intuitive assertions for common scenarios.

Count and emptiness checks
Contains and membership tests
Generic type safety
[Fact]
public void GetActiveUsers_ShouldReturnFilteredList()
{
    // Arrange
    var users = CreateTestUsers();
    
    // Act
    var activeUsers = userService.GetActiveUsers(users);
    
    // Assert - Collection validations
    activeUsers.Assert()
        .IsNotNull()
        .IsNotEmpty<User>()
        .HasCount<User>(3)
        .Contains(users.First(u => u.IsActive))
        .DoesNotContain(users.First(u => !u.IsActive));
        
    // Validate each user in collection
    foreach (var user in activeUsers)
    {
        user.Assert()
            .Satisfies(u => u.IsActive, "User should be active");
    }
}

Custom Objects & Context

Test complex objects with contextual information and custom validation predicates.

Contextual error messages
Custom validation logic
Domain-specific assertions
[Fact]
public void CreateOrder_ShouldReturnValidOrder()
{
    // Arrange
    var customer = new Customer { Id = 1, Name = "John Doe" };
    var items = CreateTestItems();
    
    // Act
    var order = orderService.CreateOrder(customer, items);
    
    // Assert with context
    order.Assert()
        .WithContext("Order creation validation")
        .IsNotNull()
        .IsOfType<Order>()
        .Satisfies(o => o.Customer.Id == 1, "Customer should match")
        .Satisfies(o => o.Items.Count > 0, "Should have items")
        .Satisfies(o => o.Total > 0, "Total should be positive")
        .Satisfies(o => o.Status == OrderStatus.Pending, 
                   "New order should be pending");
}

Advanced Testing Patterns

Combine Assertive with complex testing scenarios including exception handling and edge cases.

Method chaining validation
Complex predicate logic
Edge case handling
[Fact]
public async Task ProcessPayment_ShouldHandleValidTransaction()
{
    // Arrange
    var payment = new Payment 
    { 
        Amount = 99.99m, 
        Currency = "USD",
        Method = PaymentMethod.CreditCard
    };
    
    // Act
    var result = await paymentService.ProcessAsync(payment);
    
    // Assert - Complex validation chain
    result.Assert()
        .WithContext("Payment processing result")
        .IsNotNull()
        .Satisfies(r => r.IsSuccess, "Payment should succeed")
        .Satisfies(r => !string.IsNullOrEmpty(r.TransactionId),
                   "Should have transaction ID")
        .Satisfies(r => r.ProcessedAt <= DateTime.UtcNow,
                   "Processing time should be valid")
        .Fails(r => r.HasErrors, "Should not have errors");
}

Test Framework Integration

Noundry.Assertive works seamlessly with all popular .NET testing frameworks.

xUnit Integration

Perfect integration with xUnit.net for modern .NET testing with theories and parameterized tests.

dotnet add package xunit
dotnet add package xunit.runner.visualstudio
dotnet add package Noundry.Assertive
using Noundry.Assertive;
using Xunit;

public class CalculatorTests
{
    [Fact]
    public void Add_TwoNumbers_ShouldReturnSum()
    {
        var result = new Calculator().Add(2, 3);
        result.Assert().IsEqualTo(5);
    }
    
    [Theory]
    [InlineData(1, 2, 3)]
    [InlineData(10, 15, 25)]
    public void Add_ParameterizedTest(int a, int b, int expected)
    {
        var result = new Calculator().Add(a, b);
        result.Assert()
            .IsEqualTo(expected)
            .Satisfies(r => r >= a && r >= b);
    }
}

NUnit Integration

Seamless integration with NUnit testing framework for comprehensive test suites.

dotnet add package NUnit
dotnet add package NUnit3TestAdapter
dotnet add package Noundry.Assertive
using Noundry.Assertive;
using NUnit.Framework;

[TestFixture]
public class StringHelperTests
{
    [Test]
    public void FormatName_ShouldCapitalize()
    {
        var result = StringHelper.FormatName("john doe");
        
        result.Assert()
            .IsNotNull()
            .IsEqualTo("John Doe");
    }
    
    [TestCase("", ExpectedResult = true)]
    [TestCase(null, ExpectedResult = true)]
    [TestCase("test", ExpectedResult = false)]
    public bool IsNullOrEmpty_TestCases(string input)
    {
        var result = string.IsNullOrEmpty(input);
        
        // Can be used in expression context
        return result.Assert().IsOfType<bool>().Value;
    }
}

MSTest Integration

Full support for Microsoft's MSTest framework with data-driven testing capabilities.

dotnet add package MSTest.TestFramework
dotnet add package MSTest.TestAdapter
dotnet add package Noundry.Assertive
using Noundry.Assertive;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class DataServiceTests
{
    [TestMethod]
    public void GetUser_WithValidId_ShouldReturnUser()
    {
        var user = dataService.GetUser(1);
        
        user.Assert()
            .IsNotNull()
            .Satisfies(u => u.Id == 1);
    }
    
    [DataTestMethod]
    [DataRow("test@example.com", true)]
    [DataRow("invalid-email", false)]
    public void ValidateEmail_TestCases(string email, bool expected)
    {
        var result = validator.IsValidEmail(email);
        
        result.Assert().IsEqualTo(expected);
    }
}

NUnit Integration

Works beautifully with NUnit's rich assertion framework and test case attributes.

dotnet add package NUnit
dotnet add package NUnit3TestAdapter
dotnet add package Noundry.Assertive
using Noundry.Assertive;
using NUnit.Framework;

[TestFixture]
public class OrderServiceTests
{
    [SetUp]
    public void Setup()
    {
        _orderService = new OrderService();
    }
    
    [Test]
    public void CreateOrder_ShouldGenerateOrderNumber()
    {
        var order = _orderService.CreateOrder();
        
        order.OrderNumber.Assert()
            .IsNotNull()
            .Satisfies(on => on.StartsWith("ORD-"));
    }
    
    [TestCase(0, ExpectedResult = false)]
    [TestCase(-1, ExpectedResult = false)]
    [TestCase(1, ExpectedResult = true)]
    public bool IsValidQuantity_TestCases(int quantity)
    {
        var result = _orderService.IsValidQuantity(quantity);
        
        return result.Assert().IsOfType<bool>().Value;
    }
}

MSTest Integration

Native integration with Microsoft's testing framework for enterprise and Visual Studio environments.

dotnet add package MSTest.TestFramework
dotnet add package MSTest.TestAdapter
dotnet add package Noundry.Assertive
using Noundry.Assertive;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class BusinessLogicTests
{
    [TestInitialize]
    public void Initialize()
    {
        _businessService = new BusinessService();
    }
    
    [TestMethod]
    public void CalculateTotal_ShouldIncludeTax()
    {
        var total = _businessService.CalculateTotal(100m, 0.08m);
        
        total.Assert()
            .WithContext("Tax calculation")
            .IsEqualTo(108m)
            .IsInRange(100m, 200m);
    }
    
    [DataTestMethod]
    [DataRow(100, 0.05, 105)]
    [DataRow(200, 0.10, 220)]
    public void TaxCalculation_DataDriven(decimal amount, decimal rate, decimal expected)
    {
        var result = _businessService.CalculateTotal(amount, rate);
        result.Assert().IsEqualTo(expected);
    }
}

Error Handling & Best Practices

Understanding how Assertive handles errors and following best practices for optimal testing.

Error Handling

Assertive throws AssertionException when assertions fail, providing clear debugging information.

Clear Error Messages

Detailed descriptions of what went wrong

Expected vs Actual

Properties showing expected and actual values

Context Information

Optional context for complex validation scenarios

try
{
    42.Assert()
        .WithContext("Age validation")
        .IsEqualTo(18);
}
catch (AssertionException ex)
{
    // ex.Message: "Age validation failed..."
    // ex.Expected: 18
    // ex.Actual: 42
}

Best Practices

Use Descriptive Messages

Provide clear context in Satisfies and Fails methods

.Satisfies(x => x.IsValid, "User should pass validation")

Chain Assertions Logically

Order assertions from general to specific

result.Assert().IsNotNull().IsOfType<User>().Satisfies(...)

Add Context for Complex Validations

Use WithContext for better error diagnostics

user.Assert().WithContext("Registration flow").Satisfies(...)

Combine with Test Frameworks

Works with any .NET testing framework

// xUnit, NUnit, MSTest - all supported

Ready to Write Better Tests?

Start using Noundry.Assertive today and transform your test code into readable, expressive specifications.