dotnet-testing-awesome-assertions-guide
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAwesomeAssertions 流暢斷言指南
AwesomeAssertions Fluent Assertions Guide
本技能提供使用 AwesomeAssertions 進行高品質測試斷言的完整指南,涵蓋基礎語法、進階技巧與最佳實踐。
This skill provides a complete guide to writing high-quality test assertions with AwesomeAssertions, covering basic syntax, advanced techniques, and best practices.
適用情境
Use Cases
當被要求執行以下任務時,請使用此技能:
- 撰寫清晰、可讀性高的測試斷言
- 比對複雜物件或集合內容
- 驗證例外狀況的拋出與訊息
- 使用流暢語法(Should/Be/Contain)進行測試驗證
- 將原生 Assert 替換為 AwesomeAssertions
Use this skill when you need to perform the following tasks:
- Write clear, highly readable test assertions
- Compare complex objects or collection contents
- Verify exception throwing and messages
- Perform test validation using fluent syntax (Should/Be/Contain)
- Replace native Assert with AwesomeAssertions
關於 AwesomeAssertions
About AwesomeAssertions
AwesomeAssertions 是 FluentAssertions 的社群分支版本,使用 Apache 2.0 授權,完全免費且無商業使用限制。
AwesomeAssertions is a community fork of FluentAssertions, licensed under Apache 2.0, completely free with no commercial usage restrictions.
核心特色
Core Features
- ✅ 完全免費:Apache 2.0 授權,適合商業專案使用
- 🔗 流暢語法:支援方法鏈結的自然語言風格
- 📦 豐富斷言:涵蓋物件、集合、字串、數值、例外等各種類型
- 💬 優秀錯誤訊息:提供詳細且易理解的失敗資訊
- ⚡ 高性能:優化的實作確保測試執行效率
- 🔧 可擴展:支援自訂 Assertions 方法
- ✅ Completely Free: Apache 2.0 license, suitable for commercial projects
- 🔗 Fluent Syntax: Supports method chaining in natural language style
- 📦 Rich Assertions: Covers various types including objects, collections, strings, numbers, exceptions, etc.
- 💬 Excellent Error Messages: Provides detailed and easy-to-understand failure information
- ⚡ High Performance: Optimized implementation ensures test execution efficiency
- 🔧 Extensible: Supports custom Assertions methods
與 FluentAssertions 的關係
Relationship with FluentAssertions
AwesomeAssertions 是 FluentAssertions 的社群 fork,主要差異:
| 項目 | FluentAssertions | AwesomeAssertions |
|---|---|---|
| 授權 | 商業專案需付費 | Apache 2.0(完全免費) |
| 命名空間 | | |
| API 相容性 | 原版 | 高度相容 |
| 社群支援 | 官方維護 | 社群維護 |
AwesomeAssertions is a community fork of FluentAssertions. The main differences are:
| Item | FluentAssertions | AwesomeAssertions |
|---|---|---|
| License | Paid for commercial projects | Apache 2.0 (completely free) |
| Namespace | | |
| API Compatibility | Original version | Highly compatible |
| Community Support | Officially maintained | Community maintained |
安裝與設定
Installation and Configuration
NuGet 套件安裝
NuGet Package Installation
bash
undefinedbash
undefined.NET CLI
.NET CLI
dotnet add package AwesomeAssertions
dotnet add package AwesomeAssertions
Package Manager Console
Package Manager Console
Install-Package AwesomeAssertions
undefinedInstall-Package AwesomeAssertions
undefinedcsproj 設定(推薦)
csproj Configuration (Recommended)
xml
<ItemGroup>
<PackageReference Include="AwesomeAssertions" Version="9.1.0" PrivateAssets="all" />
</ItemGroup>xml
<ItemGroup>
<PackageReference Include="AwesomeAssertions" Version="9.1.0" PrivateAssets="all" />
</ItemGroup>命名空間引用
Namespace Reference
csharp
using AwesomeAssertions;
using Xunit;csharp
using AwesomeAssertions;
using Xunit;核心 Assertions 語法
Core Assertions Syntax
所有 Assertions 皆以 開始,搭配流暢方法鏈結。
.Should()| 類別 | 常用方法 | 說明 |
|---|---|---|
| 物件 | | 空值、類型、相等性檢查 |
| 字串 | | 內容、模式、忽略大小寫比對 |
| 數值 | | 比較、範圍、浮點精度 |
| 集合 | | 數量、內容、順序、條件 |
| 例外 | | 例外類型、訊息、巢狀例外 |
| 非同步 | | 非同步例外與完成驗證 |
📖 完整語法範例與程式碼請參閱 references/core-assertions-syntax.md
All Assertions start with , paired with fluent method chaining.
.Should()| Category | Common Methods | Description |
|---|---|---|
| Object | | Null value, type, and equality checks |
| String | | Content, pattern, and case-insensitive comparison |
| Number | | Comparison, range, and floating-point precision |
| Collection | | Quantity, content, order, and condition checks |
| Exception | | Exception type, message, and nested exception checks |
| Async | | Async exception and completion validation |
📖 For complete syntax examples and code, refer to references/core-assertions-syntax.md
進階技巧:複雜物件比對
Advanced Technique: Complex Object Comparison
使用 搭配 進行深度物件比較:
BeEquivalentTo()options- 排除屬性:— 排除自動生成欄位
options.Excluding(u => u.Id) - 動態排除:— 按模式排除
options.Excluding(ctx => ctx.Path.EndsWith("At")) - 循環參考:
options.IgnoringCyclicReferences().WithMaxRecursionDepth(10)
Use with for deep object comparison:
BeEquivalentTo()options- Exclude Properties: — Exclude auto-generated fields
options.Excluding(u => u.Id) - Dynamic Exclusion: — Exclude by pattern
options.Excluding(ctx => ctx.Path.EndsWith("At")) - Cyclic References:
options.IgnoringCyclicReferences().WithMaxRecursionDepth(10)
進階技巧:自訂 Assertions 擴展
Advanced Technique: Custom Assertions Extension
建立領域特定擴展方法,如 ,以及可重用排除擴展如 。
product.Should().BeValidProduct()ExcludingAuditFields()參考 templates/custom-assertions-template.cs 瞭解完整實作。
📖 完整範例請參閱 references/complex-object-assertions.md
Create domain-specific extension methods such as , and reusable exclusion extensions like .
product.Should().BeValidProduct()ExcludingAuditFields()Refer to templates/custom-assertions-template.cs for complete implementation.
📖 For complete examples, refer to references/complex-object-assertions.md
效能最佳化策略
Performance Optimization Strategies
- 大量資料:先用 快速檢查數量,再抽樣驗證(避免全量
HaveCount())BeEquivalentTo - 選擇性比對:使用匿名物件 + 只驗證關鍵屬性
ExcludingMissingMembers()
csharp
// 選擇性屬性比對 — 只驗證關鍵欄位
order.Should().BeEquivalentTo(new
{
CustomerId = 123,
TotalAmount = 999.99m,
Status = "Pending"
}, options => options.ExcludingMissingMembers());- Large Datasets: First use to quickly check quantity, then validate by sampling (avoid full
HaveCount())BeEquivalentTo - Selective Comparison: Use anonymous objects + to only validate key properties
ExcludingMissingMembers()
csharp
// Selective property comparison — only validate key fields
order.Should().BeEquivalentTo(new
{
CustomerId = 123,
TotalAmount = 999.99m,
Status = "Pending"
}, options => options.ExcludingMissingMembers());最佳實踐與團隊標準
Best Practices and Team Standards
測試命名規範
Test Naming Conventions
遵循 模式(如 )。
方法_情境_預期結果CreateUser_有效電子郵件_應回傳啟用的使用者Follow the pattern (e.g., ).
Method_Scenario_ExpectedResultCreateUser_ValidEmail_ShouldReturnEnabledUser錯誤訊息優化
Error Message Optimization
在斷言中加入 字串,提供清晰的失敗上下文:
becausecsharp
result.IsSuccess.Should().BeFalse("because negative payment amounts are not allowed");Add a string in assertions to provide clear failure context:
becausecsharp
result.IsSuccess.Should().BeFalse("because negative payment amounts are not allowed");AssertionScope 使用
Using AssertionScope
使用 收集多個失敗訊息,一次顯示所有問題:
AssertionScopecsharp
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");
}Use to collect multiple failure messages and display all issues at once:
AssertionScopecsharp
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");
}常見情境與解決方案
Common Scenarios and Solutions
| 情境 | 關鍵技巧 |
|---|---|
| API 回應驗證 | |
| 資料庫實體驗證 | |
| 事件驗證 | 訂閱捕獲事件後逐一驗證屬性 |
📖 完整程式碼範例請參閱 references/common-scenarios.md
| Scenario | Key Techniques |
|---|---|
| API Response Validation | |
| Database Entity Validation | |
| Event Validation | Capture events via subscription and validate properties one by one |
📖 For complete code examples, refer to references/common-scenarios.md
疑難排解
Troubleshooting
問題 1:BeEquivalentTo 失敗但物件看起來相同
Issue 1: BeEquivalentTo fails but objects look identical
原因:可能包含自動生成欄位或時間戳記
解決方案:
csharp
// 排除動態欄位
actual.Should().BeEquivalentTo(expected, options => options
.Excluding(x => x.Id)
.Excluding(x => x.CreatedAt)
.Excluding(x => x.UpdatedAt)
);Cause: 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)
);問題 2:集合順序不同導致失敗
Issue 2: Failure due to different collection order
原因:集合順序不同
解決方案:
csharp
// 使用 BeEquivalentTo 忽略順序
actual.Should().BeEquivalentTo(expected); // 不檢查順序
// 或明確指定需要檢查順序
actual.Should().Equal(expected); // 檢查順序Cause: Different collection order
Solution:
csharp
// Use BeEquivalentTo to ignore order
actual.Should().BeEquivalentTo(expected); // Does not check order
// Or explicitly specify that order needs to be checked
actual.Should().Equal(expected); // Checks order問題 3:浮點數比較失敗
Issue 3: Floating-point comparison failure
原因:浮點數精度問題
解決方案:
csharp
// 使用精度容差
actualValue.Should().BeApproximately(expectedValue, 0.001);Cause: Floating-point precision issues
Solution:
csharp
// Use precision tolerance
actualValue.Should().BeApproximately(expectedValue, 0.001);何時使用此技能
When to Use This Skill
適用情境
Suitable Scenarios
✅ 撰寫單元測試或整合測試時
✅ 需要驗證複雜物件結構時
✅ 比對 API 回應或資料庫實體時
✅ 需要清晰的失敗訊息時
✅ 建立領域特定測試標準時
✅ When writing unit tests or integration tests
✅ When you need to validate complex object structures
✅ When comparing API responses or database entities
✅ When you need clear failure messages
✅ When establishing domain-specific testing standards
不適用情境
Unsuitable Scenarios
❌ 效能測試(使用專用 benchmarking 工具)
❌ 負載測試(使用 K6、JMeter 等)
❌ UI 測試(使用 Playwright、Selenium)
❌ Performance testing (use dedicated benchmarking tools)
❌ Load testing (use K6, JMeter, etc.)
❌ UI testing (use Playwright, Selenium)
與其他技能的配合
Collaboration with Other Skills
與 unit-test-fundamentals 搭配
With unit-test-fundamentals
先使用 建立測試結構,再使用本技能撰寫斷言:
unit-test-fundamentalscsharp
[Fact]
public void Calculator_Add_兩個正數_應回傳總和()
{
// Arrange - 遵循 3A Pattern
var calculator = new Calculator();
// Act
var result = calculator.Add(2, 3);
// Assert - 使用 AwesomeAssertions
result.Should().Be(5);
}First use to build the test structure, then use this skill to write assertions:
unit-test-fundamentalscsharp
[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);
}與 test-naming-conventions 搭配
With test-naming-conventions
使用 的命名規範,搭配本技能的斷言:
test-naming-conventionscsharp
[Fact]
public void CreateUser_有效資料_應回傳啟用使用者()
{
var user = userService.CreateUser("test@example.com");
user.Should().NotBeNull()
.And.BeOfType<User>();
user.IsActive.Should().BeTrue();
}Use the naming conventions from paired with assertions from this skill:
test-naming-conventionscsharp
[Fact]
public void CreateUser_ValidData_ShouldReturnEnabledUser()
{
var user = userService.CreateUser("test@example.com");
user.Should().NotBeNull()
.And.BeOfType<User>();
user.IsActive.Should().BeTrue();
}與 xunit-project-setup 搭配
With xunit-project-setup
在 建立的專案中安裝並使用 AwesomeAssertions。
xunit-project-setupInstall and use AwesomeAssertions in projects set up with .
xunit-project-setup參考資源
Reference Resources
原始文章
Original Articles
本技能內容提煉自「老派軟體工程師的測試修練 - 30 天挑戰」系列文章:
-
Day 04 - AwesomeAssertions 基礎應用與實戰技巧
-
Day 05 - AwesomeAssertions 進階技巧與複雜情境應用
This skill is extracted from the "Old-School Software Engineer's Test Training - 30-Day Challenge" series:
-
Day 04 - AwesomeAssertions Basic Application and Practical Skills
- 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 官方文件:https://awesomeassertions.org/
- AwesomeAssertions GitHub: https://github.com/AwesomeAssertions/AwesomeAssertions
- AwesomeAssertions Official Documentation: https://awesomeassertions.org/
相關文章
Related Articles
- Fluent Assertions 授權變化討論:https://www.dotblogs.com.tw/mrkt/2025/04/19/152408
- Fluent Assertions License Change Discussion: https://www.dotblogs.com.tw/mrkt/2025/04/19/152408
總結
Summary
AwesomeAssertions 提供了強大且可讀的斷言語法,是撰寫高品質測試的重要工具。透過:
- 流暢語法:讓測試程式碼更易讀
- 豐富斷言:涵蓋各種資料類型
- 自訂擴展:建立領域特定斷言
- 效能優化:處理大量資料情境
- 完全免費:Apache 2.0 授權無商業限制
記住:好的斷言不僅能驗證結果,更能清楚表達預期行為,並在失敗時提供有用的診斷資訊。
參考 templates/assertion-examples.cs 查看更多實用範例。
AwesomeAssertions provides a powerful and readable assertion syntax, which is an important tool for writing high-quality tests. Through:
- Fluent Syntax: Makes test code more readable
- Rich Assertions: Covers various data types
- Custom Extensions: Build domain-specific assertions
- Performance Optimization: Handle large dataset scenarios
- Completely Free: Apache 2.0 license with no commercial restrictions
Remember: Good assertions not only validate results but also clearly express expected behavior and provide useful diagnostic information when failures occur.
Refer to templates/assertion-examples.cs for more practical examples.