使用 xUnit 快速編寫 .NET 應用單元測試
前言
在當今快速迭代的軟件開發環境中,單元測試已成為保障代碼質量和項目可靠性的重要基石,通過驗證程序最小單元(如函數、方法、類等)的獨立行為,能夠在開發階段快速發現邏輯錯誤或邊界條件問題。今天大姚將帶領大家使用 xUnit 快速編寫 .NET 應用單元測試。
項目介紹
xUnit 是一個開源、免費、以社區為中心的 .NET 單元測試框架,是用于 C# 和 F#(其他 .NET 語言可能也能運行,但未提供官方支持)進行單元測試的最新技術。xUnit 能夠與 Visual Studio、Visual Studio Code、ReSharper、CodeRush 和 TestDriven.NET 兼容。它是.NET 基金會的一部分,并遵循其行為準則。
單元測試最佳做法
微軟官方出品的 .NET 單元測試最佳做法:https://learn.microsoft.com/zh-cn/dotnet/core/testing/unit-testing-best-practices
- 避免基礎結構依賴項。
- 以最精簡方式編寫通過測試。
- 避免使用魔法字符串。
- 避免在單元測試中編寫代碼邏輯。
- 遵循測試命名標準:
- 要測試的方法的名稱。
- 測試方法的情境。
- 調用方案時的預期行為。
命名標準非常重要,因為它們有助于表達測試目的和應用程序。測試不僅僅是確保代碼正常工作。它們還提供文檔。只需查看單元測試套件,即可推斷代碼的行為,不必查看代碼本身。此外,測試失敗時,可以確切地看到哪些方案不符合預期。

單元測試基本步驟
我們在編寫單元測試的時候通常遵循 3A 模式(Arrange-Act-Assert),這是單元測試的核心方法論:
- Arrange(準備階段): 該階段用于模擬數據、初始化對象等準備工作。
- Act(執行階段): 該階段用于準備好的數據調用要測試的最小單元方法。
- Assert(斷言階段): 該階段是單元測試中的驗證環節,它通過將目標方法返回的實際結果與預期結果進行比對,來判定測試是否通過。

創建單元測試項目
因為 xUnit 框架與 Visual Studio 是兼容的,我們可以直接在 Visual Studio 中搜索:xUnit 測試項目 模板,然后創建一個名為:xUnitExercise 的 .NET 9 單元測試項目。


編寫簡單的單元測試
public class UnitTest
{
/// <summary>
/// 測試 Calculator 的 Add 方法功能
/// 驗證兩個正數相加返回正確的和
/// </summary>
[Fact]// 標識這是一個獨立的測試用例
public void Add_TwoPositiveNumbers_ReturnsCorrectSum()
{
// ===== Arrange(準備階段) =====
var calculator = new Calculator();
int num1 = 5;
int num2 = 7;
int expected = 12;
// ===== Act(執行階段) =====
int actual = calculator.Add(num1, num2);
// ===== Assert(斷言階段) =====
Assert.Equal(expected, actual);
}
/// <summary>
/// 測試 Calculator 的 Divide 方法異常處理
/// 驗證除數為零時正確拋出 DivideByZeroException 異常
/// </summary>
[Fact]
public void Divide_ByZero_ThrowsDivideByZeroException()
{
// Arrange
var calculator = new Calculator();
int dividend = 10;
int divisor = 0; //觸發異常的除數
// Act & Assert
// 驗證執行除法時是否拋出特定異常
var exception = Assert.Throws<DivideByZeroException>(
() => calculator.Divide(dividend, divisor));
// 驗證異常消息是否符合預期
Assert.Equal("除數不能為零", exception.Message);
}
/// <summary>
/// 參數化測試 Calculator 的 IsEven 方法功能
/// 驗證不同輸入數值的奇偶判斷是否正確
/// </summary>
/// <param name="number">測試輸入值</param>
/// <param name="expected">預期結果(true=偶數,false=奇數)</param>
[Theory] // 標識這是一個參數化測試
[InlineData(4, true)] // 測試數據1:偶數4,預期true
[InlineData(7, false)] // 測試數據2:奇數7,預期false
[InlineData(8, false)] // 測試數據3:偶數8,預期false 【這里是特意為了查看預期結果不一致的情況】
public void IsEven_Number_ReturnsCorrectResult(int number, bool expected)
{
// Arrange
var calculator = new Calculator();
// Act
bool actual = calculator.IsEven(number);
// Assert
Assert.Equal(expected, actual);
}
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
public bool IsEven(int number)
{
return number % 2 == 0;
}
public double Divide(int dividend, int divisor)
{
if (divisor == 0)
throw new DivideByZeroException("除數不能為零");
return (double)dividend / divisor;
}
}
}
運行單元測試
選擇項目右鍵 => 運行測試:


或者直接在對應的方法正上方選擇 Run:


調試單元測試
選擇項目右鍵 => 運行調試:


或者直接在對應的方法正上方選擇 Debug:


項目源碼地址
更多項目實用功能和特性歡迎前往項目開源地址查看??,別忘了給項目一個Star支持??。
- GitHub開源地址:https://github.com/xunit/xunit
- 本文示例源碼地址:https://github.com/YSGStudyHards/DotNetExercises/tree/master/xUnitExercise
優秀項目和框架精選
該項目已收錄到C#/.NET/.NET Core優秀項目和框架精選中,關注優秀項目和框架精選能讓你及時了解C#、.NET和.NET Core領域的最新動態和最佳實踐,提高開發工作效率和質量。坑已挖,歡迎大家踴躍提交PR推薦或自薦(讓優秀的項目和框架不被埋沒??)。
- GitHub開源地址:https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.md
- Gitee開源地址:https://gitee.com/ysgdaydayup/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.md
DotNetGuide技術社區
- DotNetGuide技術社區是一個面向.NET開發者的開源技術社區,旨在為開發者們提供全面的C#/.NET/.NET Core相關學習資料、技術分享和咨詢、項目框架推薦、求職和招聘資訊、以及解決問題的平臺。
- 在DotNetGuide技術社區中,開發者們可以分享自己的技術文章、項目經驗、學習心得、遇到的疑難技術問題以及解決方案,并且還有機會結識志同道合的開發者。
- 我們致力于構建一個積極向上、和諧友善的.NET技術交流平臺。無論您是初學者還是有豐富經驗的開發者,我們都希望能為您提供更多的價值和成長機會。
作者名稱:追逐時光者
作者簡介:一個熱愛編程、善于分享、喜歡學習、探索、嘗試新事物和新技術的全棧軟件工程師。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,否則保留追究法律責任的權利。如果該篇文章對您有幫助的話,可以點一下右下角的【♥推薦♥】,希望能夠持續的為大家帶來好的技術文章,文中可能存在描述不正確的地方,歡迎指正或補充,不勝感激。

浙公網安備 33010602011771號