跳到正文
cccskills
免费在 GitHub 公开

dotnet-testing-awesome-assertions-guide

Using AwesomeAssertions for fluent and readable test assertion skill. Used when writing clear assertions, comparing objects, validating collections, handling complex comparisons. Covers Should(), BeEquivalentTo(), Contain(), ThrowAsync() and complete API. Keywords: assertions, awesome assertions, fluent assertions, assertion, fluent assertion, Should(), Be(), BeEquivalentTo, Contain, ThrowAsync, NotBeNull, object comparison, collection validation, exception assertion, AwesomeAssertions, FluentAssertions, fluent syntax

中文简介正在准备中。当前显示原文说明。

查看安装方法

包含的文件(1)

  • SKILL.md10.3 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Source: kevintsengtw/dotnet-testing-agent-skills (MIT). Ported into dotnet-agent-harness.

AwesomeAssertions Fluent Assertion Guide

This skill provides a complete guide for writing high-quality test assertions using AwesomeAssertions, covering basic syntax, advanced techniques, and best practices.

Applicable Scenarios

Use this skill when asked to perform the following tasks:

  • Write clear, highly readable test assertions
  • Compare complex objects or collection contents
  • Verify exception throwing and messages
  • Use fluent syntax (Should/Be/Contain) for test validation
  • Replace native Assert with AwesomeAssertions

About AwesomeAssertions

AwesomeAssertions is a community fork version of FluentAssertions, using Apache 2.0 license, completely free with no commercial usage restrictions.

Core Features

  • Fully Free: Apache 2.0 license, suitable for commercial projects
  • Fluent Syntax: Supports natural language style method chaining
  • Rich Assertions: Covers objects, collections, strings, numbers, exceptions, and various other types
  • Excellent Error Messages: Provides detailed and easy-to-understand failure information
  • High Performance: Optimized implementation ensures test execution efficiency
  • Extensible: Supports custom Assertion methods

Relationship with FluentAssertions

AwesomeAssertions is a community fork of FluentAssertions, main differences:

ItemFluentAssertionsAwesomeAssertions
LicenseCommercial projects require paymentApache 2.0 (completely free)
NamespaceFluentAssertionsAwesomeAssertions
API CompatibilityOriginalHighly compatible
Community SupportOfficial maintenanceCommunity maintenance

Installation and Setup

NuGet Package Installation

# .NET CLI
dotnet add package AwesomeAssertions

# Package Manager Console
Install-Package AwesomeAssertions
```text

### csproj Setup (Recommended)

```xml
<ItemGroup>
  <PackageReference Include="AwesomeAssertions" Version="9.1.0" PrivateAssets="all" />
</ItemGroup>
```text

### Namespace Import

```csharp
using AwesomeAssertions;
using Xunit;
```text

---

## Core Assertions Syntax

All Assertions start with `.Should()`, combined with fluent method chaining.

| Category | Common Methods | Description |
|------|----------|------|
| **Object** | `NotBeNull()`, `BeOfType<T>()`, `BeEquivalentTo()` | Null, type, equality checks |
| **String** | `Contain()`, `StartWith()`, `MatchRegex()`, `BeEquivalentTo()` | Content, patterns, case-insensitive comparison |
| **Number** | `BeGreaterThan()`, `BeInRange()`, `BeApproximately()` | Comparison, range, floating point precision |
| **Collection** | `HaveCount()`, `Contain()`, `BeEquivalentTo()`, `AllSatisfy()` | Count, content, order, conditions |
| **Exception** | `Throw<T>()`, `NotThrow()`, `WithMessage()`, `WithInnerException()` | Exception types, messages, nested exceptions |
| **Async** | `ThrowAsync<T>()`, `CompleteWithinAsync()` | Async exceptions and completion validation |

> Full syntax examples and code please refer to [references/core-assertions-syntax.md](references/core-assertions-syntax.md)

---

## Advanced Techniques: Complex Object Comparison

Use `BeEquivalentTo()` with `options` for deep object comparison:

- **Exclude properties**: `options.Excluding(u => u.Id)` — exclude auto-generated fields
- **Dynamic exclusion**: `options.Excluding(ctx => ctx.Path.EndsWith("At"))` — exclude by pattern
- **Circular references**: `options.IgnoringCyclicReferences().WithMaxRecursionDepth(10)`

---

## Advanced Techniques: Custom Assertions Extension

Create domain-specific extension methods, like `product.Should().BeValidProduct()`, and reusable exclusion extensions like `ExcludingAuditFields()`.

Refer to [templates/custom-assertions-template.cs](templates/custom-assertions-template.cs) for complete implementation.

> Full examples please refer to [references/complex-object-assertions.md](references/complex-object-assertions.md)

---

## Performance Optimization Strategies

- **Large data**: First use `HaveCount()` for quick count check, then sample validation (avoid full `BeEquivalentTo`)
- **Selective comparison**: Use anonymous objects + `ExcludingMissingMembers()` to only validate key properties

```csharp
// Selective property comparison — only validate key fields
order.Should().BeEquivalentTo(new
{
    CustomerId = 123,
    TotalAmount = 999.99m,
    Status = "Pending"
}, options => options.ExcludingMissingMembers());
```text

---

## Best Practices and Team Standards

### Test Naming Conventions

Follow `Method_Scenario_ExpectedResult` pattern (e.g., `CreateUser_WithValidEmail_ShouldReturnEnabledUser`).

### Error Message Optimization

Add `because` string in assertions to provide clear failure context:

```csharp
result.IsSuccess.Should().BeFalse("because negative payment amounts are not allowed");
```text

### AssertionScope Usage

Use `AssertionScope` to collect multiple failure messages, display all problems at once:

```csharp
using (new AssertionScope())
{
    user.Should().NotBeNull("User creation should not fail");
    user.Id.Should().BeGreaterThan(0, "User should have valid ID");
    user.Email.Should().NotBeNullOrEmpty("Email is required");
}
```text

---

## Common Scenarios and Solutions

| Scenario | Key Technique |
|------|----------|
| API response validation | `BeEquivalentTo()` + `Including()` selective comparison |
| Database entity validation | `BeEquivalentTo()` + `Excluding()` exclude auto-generated fields |
| Event validation | Subscribe to capture events then validate properties one by one |

> Full code examples please refer to [references/common-scenarios.md](references/common-scenarios.md)

---

## Troubleshooting

### Problem 1: BeEquivalentTo fails but objects look the same

**Reason**: May contain auto-generated fields or timestamps

**Solution**:

```csharp
// Exclude dynamic fields
actual.Should().BeEquivalentTo(expected, options => options
    .Excluding(x => x.Id)
    .Excluding(x => x.CreatedAt)
    .Excluding(x => x.UpdatedAt)
);
```text

### Problem 2: Collection order different causes failure

**Reason**: Collection order is different

**Solution**:

```csharp
// Use BeEquivalentTo ignore order
actual.Should().BeEquivalentTo(expected); // Does not check order

// Or explicitly specify need to check order
actual.Should().Equal(expected); // Checks order
```text

### Problem 3: Floating point comparison fails

**Reason**: Floating point precision issues

**Solution**:

```csharp
// Use precision tolerance
actualValue.Should().BeApproximately(expectedValue, 0.001);
```text

---

## When to Use This Skill

### Applicable Scenarios

Write unit tests or integration tests
Need to validate complex object structures
Compare API responses or database entities
Need clear failure messages
Establish domain-specific testing standards

### Not Applicable Scenarios

Performance testing (use dedicated benchmarking tools)
Load testing (use K6, JMeter, etc.)
UI testing (use Playwright, Selenium)

---

## Integration with Other Skills

### Integration with unit-test-fundamentals

First use `unit-test-fundamentals` to establish test structure, then use this skill to write assertions:

```csharp
[Fact]
public void Calculator_Add_TwoPositiveNumbers_ShouldReturnSum()
{
    // Arrange - follow 3A Pattern
    var calculator = new Calculator();

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

    // Assert - use AwesomeAssertions
    result.Should().Be(5);
}
```text

### Integration with test-naming-conventions

Use `test-naming-conventions` naming conventions, combined with this skill's assertions:

```csharp
[Fact]
public void CreateUser_WithValidData_ShouldReturnEnabledUser()
{
    var user = userService.CreateUser("test@example.com");

    user.Should().NotBeNull()
        .And.BeOfType<User>();
    user.IsActive.Should().BeTrue();
}
```text

### Integration with xunit-project-setup

Install and use AwesomeAssertions in projects created with `xunit-project-setup`.

---

## Reference Resources

### Original Articles

This skill content is extracted from "Old School Software Engineer's Testing Practice - 30 Day Challenge" series:

- **Day 04 - AwesomeAssertions Basic Application and Practical Techniques**
  - Ironman Article: https://ithelp.ithome.com.tw/articles/10374188
  - Sample Code: https://github.com/kevintsengtw/30Days_in_Testing_Samples/tree/main/day04

- **Day 05 - AwesomeAssertions Advanced Techniques and Complex Scenario Applications**
  - Ironman Article: https://ithelp.ithome.com.tw/articles/10374425
  - Sample Code: https://github.com/kevintsengtw/30Days_in_Testing_Samples/tree/main/day05

### Official Resources

- **AwesomeAssertions GitHub**: https://github.com/AwesomeAssertions/AwesomeAssertions
- **AwesomeAssertions Official Documentation**: https://awesomeassertions.org/

### Related Articles

- **Fluent Assertions License Change Discussion**: https://www.dotblogs.com.tw/mrkt/2025/04/19/152408

---

## Summary

AwesomeAssertions provides powerful and readable assertion syntax, an important tool for writing high-quality tests. Through:

1. **Fluent Syntax**: Makes test code more readable
2. **Rich Assertions**: Covers various data types
3. **Custom Extensions**: Establish domain-specific assertions
4. **Performance Optimization**: Handle large data scenarios
5. **Completely Free**: Apache 2.0 license with no commercial restrictions

Remember: Good assertions not only validate results but clearly express expected behavior and provide useful diagnostic information when failing.

Refer to [templates/assertion-examples.cs](templates/assertion-examples.cs) for more practical examples.

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

Patterns and techniques for evaluating and improving AI agent outputs.

中文简介正在准备中。当前显示原文说明。

rudironsoni/Synaxis22026年3月17日 更新

Comprehensive AI prompt engineering safety review and improvement prompt. Analyzes prompts for safety, bias, security vulnerabilities, and effectiveness while providing detailed improvement recommendations.

中文简介正在准备中。当前显示原文说明。

rudironsoni/Synaxis22026年3月17日 更新

Use when user requests research requiring multiple sources, comprehensive analysis, or synthesis across topics - technical research, domain knowledge gathering, market analysis, or learning about complex subjects

中文简介正在准备中。当前显示原文说明。

rudironsoni/Synaxis22026年3月17日 更新

deep-wiki

免费

AI-powered wiki generation for code repositories with commands, agents, and skills

中文简介正在准备中。当前显示原文说明。

rudironsoni/Synaxis22026年3月17日 更新

Use when building .NET 10 or C# 14 applications; when using minimal APIs, modular monolith patterns, or feature folders; when implementing HTTP resilience, Options pattern, Channels, or validation; when seeing outdated patterns like old extension method syntax

中文简介正在准备中。当前显示原文说明。

rudironsoni/Synaxis22026年3月17日 更新

Implements accessible .NET UI. SemanticProperties, ARIA, AutomationPeer, testing per platform.

中文简介正在准备中。当前显示原文说明。

rudironsoni/Synaxis22026年3月17日 更新

查看 rudironsoni 的全部技能

报告此技能的问题