{"id":"eb78eab2-769b-46c3-9b98-217dc6a4a6e7","shortId":"DfCZSq","kind":"skill","title":"dotnet-testing-autofixture-nsubstitute-integration","tagline":"AutoFixture 與 NSubstitute 整合指南 - 實現自動模擬 (Auto-Mocking)。當需要自動建立 Mock 物件、簡化複雜相依性注入測試時使用。涵蓋 AutoNSubstituteDataAttribute、Frozen 機制、Greedy 建構策略。包含 IMapper (AutoMapper/Mapster) 等特殊相依性的客製化處理。\nMake sure to use this skill whenever the user mentions AutoFixture with NSubstitute, auto-mock","description":"# AutoFixture + NSubstitute 自動模擬整合\n\n## 核心價值\n\n- **減少樣板程式碼**：不需要手動為每個介面建立 `Substitute.For<T>()`\n- **自動處理複雜相依圖**：AutoFixture 會自動解析並建立所需的物件\n- **提升測試維護性**：當建構函式變更時，測試程式碼通常不需要同步修改\n- **保持測試重點**：讓開發者專注於測試邏輯而非物件建立\n\n---\n\n## 套件安裝與設定\n\n### 必要套件\n\n```bash\n# 核心套件\ndotnet add package AutoFixture.AutoNSubstitute\n\n# 相關套件（如尚未安裝）\ndotnet add package AutoFixture\ndotnet add package AutoFixture.Xunit2\ndotnet add package NSubstitute\ndotnet add package xunit\n```\n\n### NuGet 套件資訊\n\n| 套件名稱                      | 用途                            | NuGet 連結                                                               |\n| ----------------------------- | ------------------------------- | ------------------------------------------------------------------------ |\n| `AutoFixture.AutoNSubstitute` | AutoFixture 與 NSubstitute 整合 | [nuget.org](https://www.nuget.org/packages/AutoFixture.AutoNSubstitute/) |\n| `AutoFixture.Xunit2`          | xUnit 整合（AutoData 屬性）     | [nuget.org](https://www.nuget.org/packages/AutoFixture.Xunit2/)          |\n| `NSubstitute`                 | 模擬框架                        | [nuget.org](https://www.nuget.org/packages/NSubstitute/)                 |\n\n---\n\n## 核心概念\n\n### AutoNSubstituteCustomization 的作用\n\n當在 AutoFixture 中加入 `AutoNSubstituteCustomization` 時，它會自動：\n\n1. **偵測介面類型**：當 AutoFixture 遇到介面或抽象類別時\n2. **自動建立替身**：使用 NSubstitute 的 `Substitute.For<T>()` 建立 Mock 物件\n3. **注入相依性**：將這些替身物件注入到需要的建構函式中\n4. **保持實例一致性**：確保相同類型的替身在同一個測試中保持一致\n\n```csharp\nusing AutoFixture;\nusing AutoFixture.AutoNSubstitute;\n\n// 建立包含 AutoNSubstitute 功能的 Fixture\nvar fixture = new Fixture().Customize(new AutoNSubstituteCustomization());\n\n// 自動建立服務和其相依性\n// MyService 的所有介面相依性都會自動變成 NSubstitute 的替身\nvar service = fixture.Create<MyService>();\n```\n\n### FrozenAttribute 凍結機制\n\n`[Frozen]` 屬性用來控制測試中某個類型的實例：\n\n- 當參數被標註為 `[Frozen]` 時，AutoFixture 會建立這個類別的一個實例並**凍結**它\n- 後續在測試方法中都會使用同一個已凍結的實例\n- 這對於需要設定相依性行為然後驗證 SUT 的測試特別重要\n\n```csharp\n[Theory]\n[AutoData]\npublic async Task TestMethod(\n    [Frozen] IRepository repository,  // 這個 repository 會被凍結\n    MyService sut)                    // sut 會使用同一個 repository\n{\n    // 設定凍結實例的行為\n    repository.GetAsync(Arg.Any<int>()).Returns(someData);\n\n    // SUT 內部使用的是同一個 repository 實例\n    var result = await sut.DoSomething();\n}\n```\n\n### 參數順序的重要性\n\n使用 `[Frozen]` 時，**參數順序非常重要**：\n\n```csharp\n// 正確：Frozen 參數在 SUT 之前\npublic async Task TestMethod(\n    [Frozen] IRepository repository,\n    MyService sut)\n\n// 錯誤：SUT 會使用不同的 repository 實例\npublic async Task TestMethod(\n    MyService sut,\n    [Frozen] IRepository repository)  // 太晚凍結了\n```\n\n---\n\n## 傳統方式 vs AutoNSubstitute 方式\n\n### 傳統手動方式\n\n```csharp\n[Fact]\npublic async Task TraditionalWay()\n{\n    // Arrange - 手動建立每個相依性\n    var repository = Substitute.For<IRepository>();\n    var logger = Substitute.For<ILogger<OrderService>>();\n    var notificationService = Substitute.For<INotificationService>();\n    var cacheService = Substitute.For<ICacheService>();\n\n    var sut = new OrderService(repository, logger, notificationService, cacheService);\n\n    // 設定替身行為\n    repository.GetOrderAsync(Arg.Any<int>()).Returns(someOrder);\n\n    // Act\n    var result = await sut.GetOrderAsync(orderId);\n\n    // Assert\n    result.Should().NotBeNull();\n}\n```\n\n**問題**：\n\n- 當服務增加新相依性時，所有測試都需要修改\n- 大量重複的 `Substitute.For<T>()` 呼叫\n- 測試程式碼冗長，難以快速理解測試意圖\n\n### 使用 AutoNSubstitute 方式\n\n```csharp\n[Theory]\n[AutoDataWithCustomization]\npublic async Task WithAutoNSubstitute(\n    [Frozen] IRepository repository,\n    OrderService sut)\n{\n    // Arrange - 相依性已自動建立，只需設定需要的行為\n    repository.GetOrderAsync(Arg.Any<int>()).Returns(someOrder);\n\n    // Act\n    var result = await sut.GetOrderAsync(orderId);\n\n    // Assert\n    result.Should().NotBeNull();\n}\n```\n\n**優勢**：\n\n- 只需宣告需要互動的相依性\n- 其他相依性（logger, notificationService, cacheService）自動建立\n- 建構函式變更時，測試通常不需要修改\n\n---\n\n## 自訂 AutoData 屬性\n\n### 為什麼需要自訂 AutoData 屬性？\n\n在實際專案中，通常需要整合多種客製化設定：\n\n- **AutoNSubstituteCustomization**：自動為介面建立 NSubstitute 替身\n- **專案特定的 Customization**：如 Mapper 設定、驗證器設定等\n- **一致的測試基礎設施**：確保整個專案使用相同的設定\n\n### AutoDataWithCustomizationAttribute 實作\n\n```csharp\nusing AutoFixture;\nusing AutoFixture.AutoNSubstitute;\nusing AutoFixture.Xunit2;\n\nnamespace MyProject.Tests.AutoFixtureConfigurations;\n\n/// <summary>\n/// 包含客製化設定的 AutoData 屬性\n/// </summary>\npublic class AutoDataWithCustomizationAttribute : AutoDataAttribute\n{\n    /// <summary>\n    /// 建構函式\n    /// </summary>\n    public AutoDataWithCustomizationAttribute() : base(CreateFixture)\n    {\n    }\n\n    private static IFixture CreateFixture()\n    {\n        var fixture = new Fixture()\n            .Customize(new AutoNSubstituteCustomization())\n            .Customize(new MapsterMapperCustomization())  // 專案特定設定\n            .Customize(new DomainCustomization());        // 領域模型設定\n\n        return fixture;\n    }\n}\n```\n\n### InlineAutoDataWithCustomizationAttribute 實作\n\n用於結合固定測試值與自動產生物件：\n\n```csharp\nusing AutoFixture;\nusing AutoFixture.AutoNSubstitute;\nusing AutoFixture.Xunit2;\n\nnamespace MyProject.Tests.AutoFixtureConfigurations;\n\n/// <summary>\n/// 包含客製化設定的 InlineAutoData 屬性\n/// </summary>\npublic class InlineAutoDataWithCustomizationAttribute : InlineAutoDataAttribute\n{\n    /// <summary>\n    /// 建構函式\n    /// </summary>\n    /// <param name=\"values\">固定值（將填入測試方法的前幾個參數）</param>\n    public InlineAutoDataWithCustomizationAttribute(params object[] values)\n        : base(new AutoDataWithCustomizationAttribute(), values)\n    {\n    }\n}\n```\n\n### 重要實作細節\n\n**為什麼使用 `new AutoDataWithCustomizationAttribute()` 而不是 `CreateFixture` 方法？**\n\n```csharp\n// 錯誤：InlineAutoDataAttribute 需要 AutoDataAttribute，不是 Func<IFixture>\npublic InlineAutoDataWithCustomizationAttribute(params object[] values)\n    : base(CreateFixture, values)  // 編譯錯誤或行為異常\n\n// 正確：傳遞 AutoDataAttribute 實例\npublic InlineAutoDataWithCustomizationAttribute(params object[] values)\n    : base(new AutoDataWithCustomizationAttribute(), values)\n```\n\n原因：\n\n- `InlineAutoDataAttribute` 繼承自 `CompositeDataAttribute`\n- 它需要接收一個 `AutoDataAttribute` 實例作為資料來源提供者\n- 這樣可以重用 `AutoDataWithCustomizationAttribute` 的所有設定\n\n---\n\n## 常見相依性的客製化處理\n\n某些相依性（如 IMapper）不適合使用 Mock，而應該使用真實實例。包含 Mapster 和 AutoMapper 的客製化範例。\n\n> 完整客製化處理範例請參考 [references/dependency-customization.md](references/dependency-customization.md)\n\n---\n\n## 測試實作範例\n\n涵蓋基本測試、Frozen 相依行為設定、自動產生測試資料、InlineAutoData 參數化測試、CollectionSize 控制、IFixture 複雜資料設定、Nullable 參考類型處理等完整範例。\n\n> 完整測試實作範例請參考 [references/test-implementation-examples.md](references/test-implementation-examples.md)\n\n---\n\n## 適用場景判斷\n\n### 建議使用的場景\n\n| 場景             | 原因                               |\n| ---------------- | ---------------------------------- |\n| 服務層測試       | 通常有多個相依性，自動模擬效益最大 |\n| 複雜相依圖       | AutoFixture 自動處理多層相依性     |\n| 參數化測試       | 結合固定值與自動產生資料           |\n| 需要大量測試資料 | 減少手動建立測試資料的工作         |\n| 快速迭代開發     | 建構函式變更時測試通常不需修改     |\n\n### 謹慎使用的場景\n\n| 場景                   | 原因                                     |\n| ---------------------- | ---------------------------------------- |\n| 單一相依性測試         | 手動建立可能更清晰直覺                   |\n| 精確控制屬性值         | 需要額外的 `fixture.Build().With()` 設定 |\n| 團隊不熟悉 AutoFixture | 學習成本可能影響開發效率                 |\n| 除錯困難的場景         | 自動產生的物件可能讓除錯變複雜           |\n| 效能敏感的測試         | 物件建立的開銷可能影響執行速度           |\n\n---\n\n## 最佳實踐\n\n### 導入策略\n\n1. **漸進式採用**\n   - 從簡單的服務類別開始\n   - 逐步擴展到複雜場景\n   - 讓團隊逐漸熟悉模式\n\n2. **團隊培訓**\n   - 確保團隊理解 Frozen 機制\n   - 說明參數順序的重要性\n   - 分享除錯技巧\n\n3. **建立規範**\n   - 何時使用自動產生 vs 手動建立\n   - 自訂 Customization 的命名與組織\n   - 測試資料的控制策略\n\n### 程式碼組織\n\n```text\nMyProject.Tests/\n├── AutoFixtureConfigurations/\n│   ├── AutoDataWithCustomizationAttribute.cs\n│   ├── InlineAutoDataWithCustomizationAttribute.cs\n│   ├── AutoMapperCustomization.cs\n│   └── DomainCustomization.cs\n├── Services/\n│   ├── OrderServiceTests.cs\n│   └── ShipperServiceTests.cs\n└── ...\n```\n\n### 命名慣例\n\n- **自訂 AutoData 屬性**：`[專案名稱]AutoDataAttribute` 或 `AutoDataWithCustomizationAttribute`\n- **Customization 類別**：`[功能]Customization`（如 `MapsterMapperCustomization`）\n- **測試方法**：維持 `方法_情境_預期` 的命名模式\n\n---\n\n## 注意事項與限制\n\n### 常見陷阱\n\n1. **參數順序錯誤**\n\n   ```csharp\n   // Frozen 參數在 SUT 之後，不會生效\n   public void Test(MyService sut, [Frozen] IRepository repo)\n\n   // Frozen 參數必須在 SUT 之前\n   public void Test([Frozen] IRepository repo, MyService sut)\n   ```\n\n2. **遺忘 AutoNSubstituteCustomization**\n\n   ```csharp\n   // 沒有 AutoNSubstitute，介面會產生異常\n   var fixture = new Fixture();\n\n   // 加入 AutoNSubstituteCustomization\n   var fixture = new Fixture().Customize(new AutoNSubstituteCustomization());\n   ```\n\n3. **過度依賴自動產生**\n\n   ```csharp\n   // 測試意圖不明確\n   public void Test(Order order, Customer customer, MyService sut)\n   {\n       var result = sut.Process(order);\n       result.Should().NotBeNull();  // 驗證什麼？\n   }\n\n   // 明確控制關鍵屬性\n   public void Test(IFixture fixture, MyService sut)\n   {\n       var order = fixture.Build<Order>()\n                          .With(o => o.Status, OrderStatus.Pending)\n                          .Create();\n\n       var result = sut.Process(order);\n       result.Status.Should().Be(OrderStatus.Processed);\n   }\n   ```\n\n### 效能考量\n\n- 每個測試方法都會建立新的 Fixture 和所有相依性\n- 複雜物件圖可能增加測試執行時間\n- 考慮使用 `[ClassData]` 或 `IClassFixture<T>` 共享設定\n\n---\n\n## 相關技能\n\n| 技能名稱                     | 關聯說明                               |\n| ---------------------------- | -------------------------------------- |\n| `autofixture-basics`         | AutoFixture 基礎使用，本技能的前置知識 |\n| `autofixture-customization`  | 自訂 Customization 的進階用法          |\n| `autodata-xunit-integration` | AutoData 屬性家族的完整說明            |\n| `nsubstitute-mocking`        | NSubstitute 基礎，Mock 設定的詳細說明  |\n\n---\n\n## 輸出格式\n\n- 產生自訂 `AutoDataAttribute` 衍生類別檔案（`*AutoDataAttribute.cs`）\n- 產生 `ICustomization` 實作類別檔案（`*Customization.cs`）\n- 測試方法使用 `[Theory]` 搭配自訂 AutoData 屬性\n- `[Frozen]` 參數置於 SUT 參數之前\n- 搭配 NSubstitute 的 `Returns()` 與 `Received()` 進行行為設定與驗證\n\n## 參考資源\n\n### 原始文章\n\n本技能內容提煉自「老派軟體工程師的測試修練 - 30 天挑戰」系列文章：\n\n- **Day 13 - AutoFixture 整合 NSubstitute：自動建立 Mock 對象**\n  - 鐵人賽文章：https://ithelp.ithome.com.tw/articles/10375419\n  - 範例程式碼：https://github.com/kevintsengtw/30Days_in_Testing_Samples/tree/main/day13\n\n### 官方文件\n\n- [AutoFixture.AutoNSubstitute NuGet Package](https://www.nuget.org/packages/AutoFixture.AutoNSubstitute/)\n- [AutoFixture Documentation - Auto Mocking](https://autofixture.readthedocs.io/en/stable/)\n- [NSubstitute Documentation](https://nsubstitute.github.io/help/getting-started/)\n\n### 延伸閱讀\n\n- [使用 AutoFixture.AutoData 來改寫以前的測試程式碼 | mrkt的程式學習筆記](https://www.dotblogs.com.tw/mrkt/2024/09/29/191300)\n\n\n### 範例程式碼\n\n- [custom-autodata-attributes.cs](templates/custom-autodata-attributes.cs) - 自訂 AutoData 屬性範本\n- [frozen-patterns.cs](templates/frozen-patterns.cs) - Frozen 機制使用模式\n- [service-testing-examples.cs](templates/service-testing-examples.cs) - 服務層測試完整範例","tags":["dotnet","testing","autofixture","nsubstitute","integration","agent","skills","kevintsengtw","agent-skills","ai-assisted-development","copilot-skills","csharp"],"capabilities":["skill","source-kevintsengtw","skill-dotnet-testing-autofixture-nsubstitute-integration","topic-agent-skills","topic-ai-assisted-development","topic-copilot-skills","topic-csharp","topic-dotnet","topic-dotnet-testing","topic-github-copilot","topic-integration-testing","topic-testing","topic-unit-testing","topic-xunit"],"categories":["dotnet-testing-agent-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-autofixture-nsubstitute-integration","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add kevintsengtw/dotnet-testing-agent-skills","source_repo":"https://github.com/kevintsengtw/dotnet-testing-agent-skills","install_from":"skills.sh"}},"qualityScore":"0.461","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 23 github stars · SKILL.md body (10,583 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-24T13:02:26.368Z","embedding":null,"createdAt":"2026-04-18T23:04:25.660Z","updatedAt":"2026-04-24T13:02:26.368Z","lastSeenAt":"2026-04-24T13:02:26.368Z","tsv":"'/articles/10375419':779 '/en/stable/)':797 '/help/getting-started/)':802 '/kevintsengtw/30days_in_testing_samples/tree/main/day13':783 '/mrkt/2024/09/29/191300)':810 '/packages/autofixture.autonsubstitute/)':100,790 '/packages/autofixture.xunit2/)':109 '/packages/nsubstitute/)':115 '1':125,553,607 '13':769 '2':130,558,635 '3':139,565,655 '30':765 '4':142 'act':289,328 'add':65,71,75,79,83 'arg.any':204,286,325 'arrang':261,321 'assert':295,334 'async':188,227,241,258,313 'auto':13,43,793 'auto-mock':12,42 'autodata':104,186,347,350,378,587,724,727,748,815 'autodata-xunit-integr':723 'autodataattribut':383,452,466,482,590,738 'autodataattribute.cs':740 'autodatawithcustom':311 'autodatawithcustomizationattribut':366,382,386,439,444,475,485,592 'autodatawithcustomizationattribute.cs':578 'autofixtur':4,7,39,45,53,73,93,120,128,147,176,370,415,526,545,712,714,718,770,791 'autofixture-bas':711 'autofixture-custom':717 'autofixture.autodata':805 'autofixture.autonsubstitute':67,92,149,372,417,785 'autofixture.readthedocs.io':796 'autofixture.readthedocs.io/en/stable/)':795 'autofixture.xunit2':77,101,374,419 'autofixtureconfigur':577 'automapp':497 'automapper/mapster':27 'automappercustomization.cs':580 'autonsubstitut':151,252,307,640 'autonsubstitutecustom':117,122,160,354,399,637,647,654 'autonsubstitutedataattribut':20 'await':213,292,331 'base':387,437,460,473 'bash':62 'basic':713 'cacheservic':274,283,342 'class':381,426 'classdata':704 'collections':509 'compositedataattribut':480 'creat':690 'createfixtur':388,392,446,461 'csharp':145,184,220,255,309,368,413,448,609,638,657 'custom':158,359,397,400,404,571,593,596,652,664,665,719,721 'custom-autodata-attributes.cs':812 'customization.cs':744 'day':768 'document':792,799 'domaincustom':406 'domaincustomization.cs':581 'dotnet':2,64,70,74,78,82 'dotnet-testing-autofixture-nsubstitute-integr':1 'fact':256 'fixtur':153,155,157,394,396,409,643,645,649,651,680,700 'fixture.build':541,685 'fixture.create':168 'frozen':21,171,174,191,217,222,230,246,316,504,561,610,620,623,630,750,819 'frozen-patterns.cs':817 'frozenattribut':169 'func':454 'github.com':782 'github.com/kevintsengtw/30days_in_testing_samples/tree/main/day13':781 'greedi':23 'iclassfixtur':706 'icustom':742 'ifixtur':391,511,679 'ilogg':269 'imapp':26,490 'inlineautodata':423,507 'inlineautodataattribut':428,450,478 'inlineautodatawithcustomizationattribut':410,427,433,456,469 'inlineautodatawithcustomizationattribute.cs':579 'integr':6,726 'irepositori':192,231,247,317,621,631 'ithelp.ithome.com.tw':778 'ithelp.ithome.com.tw/articles/10375419':777 'logger':267,281,340 'make':29 'mapper':361 'mapster':495 'mapstermappercustom':402,598 'mention':38 'mock':14,16,44,137,492,731,734,774,794 'mrkt的程式學習筆記':807 'myproject.tests':576 'myproject.tests.autofixtureconfigurations':376,421 'myservic':162,197,233,244,618,633,666,681 'namespac':375,420 'new':156,159,278,395,398,401,405,438,443,474,644,650,653 'notbenul':297,336,673 'notificationservic':271,282,341 'nsubstitut':5,9,41,46,81,95,110,133,164,356,730,732,755,772,798 'nsubstitute-mock':729 'nsubstitute.github.io':801 'nsubstitute.github.io/help/getting-started/)':800 'nuget':86,90,786 'nuget.org':97,106,112 'nullabl':513 'o':687 'o.status':688 'object':435,458,471 'order':662,663,671,684,694 'orderid':294,333 'orderservic':279,319 'orderservicetests.cs':583 'orderstatus.pending':689 'orderstatus.processed':697 'packag':66,72,76,80,84,787 'param':434,457,470 'privat':389 'public':187,226,240,257,312,380,385,425,432,455,468,615,627,659,676 'receiv':759 'references/dependency-customization.md':500,501 'references/test-implementation-examples.md':516,517 'repo':622,632 'repositori':193,195,201,209,232,238,248,264,280,318 'repository.getasync':203 'repository.getorderasync':285,324 'result':212,291,330,669,692 'result.should':296,335,672 'result.status.should':695 'return':205,287,326,408,757 'servic':167,582 'service-testing-examples.cs':821 'shipperservicetests.cs':584 'skill':34 'skill-dotnet-testing-autofixture-nsubstitute-integration' 'somedata':206 'someord':288,327 'source-kevintsengtw' 'static':390 'substitute.for':51,135,265,268,272,275,302 'sure':30 'sut':182,198,199,207,224,234,236,245,277,320,612,619,625,634,667,682,752 'sut.dosomething':214 'sut.getorderasync':293,332 'sut.process':670,693 'task':189,228,242,259,314 'templates/custom-autodata-attributes.cs':813 'templates/frozen-patterns.cs':818 'templates/service-testing-examples.cs':822 'test':3,617,629,661,678 'testmethod':190,229,243 'text':575 'theori':185,310,746 'topic-agent-skills' 'topic-ai-assisted-development' 'topic-copilot-skills' 'topic-csharp' 'topic-dotnet' 'topic-dotnet-testing' 'topic-github-copilot' 'topic-integration-testing' 'topic-testing' 'topic-unit-testing' 'topic-xunit' 'traditionalway':260 'use':32,146,148,369,371,373,414,416,418 'user':37 'valu':436,440,459,462,472,476 'var':154,166,211,263,266,270,273,276,290,329,393,642,648,668,683,691 'void':616,628,660,677 'vs':251,568 'whenev':35 'withautonsubstitut':315 'www.dotblogs.com.tw':809 'www.dotblogs.com.tw/mrkt/2024/09/29/191300)':808 'www.nuget.org':99,108,114,789 'www.nuget.org/packages/autofixture.autonsubstitute/)':98,788 'www.nuget.org/packages/autofixture.xunit2/)':107 'www.nuget.org/packages/nsubstitute/)':113 'xunit':85,102,725 '一致的測試基礎設施':364 '不是':453 '不會生效':614 '不適合使用':491 '不需要手動為每個介面建立':50 '中加入':121 '之前':225,626 '之後':613 '介面會產生異常':641 '何時使用自動產生':567 '使用':132,216,306,804 '來改寫以前的測試程式碼':806 '保持實例一致性':143 '保持測試重點':58 '偵測介面類型':126 '傳統手動方式':254 '傳統方式':250 '傳遞':465 '優勢':337 '內部使用的是同一個':208 '共享設定':707 '其他相依性':339 '凍結':178 '凍結機制':170 '分享除錯技巧':564 '功能':595 '功能的':152 '加入':646 '包含':25,494 '包含客製化設定的':377,422 '原因':477,521,536 '原始文章':762 '參數之前':753 '參數化測試':508,528 '參數在':223,611 '參數必須在':624 '參數置於':751 '參數順序的重要性':215 '參數順序錯誤':608 '參數順序非常重要':219 '參考資源':761 '參考類型處理等完整範例':514 '只需宣告需要互動的相依性':338 '只需設定需要的行為':323 '呼叫':303 '命名慣例':585 '和':496 '和所有相依性':701 '問題':298 '單一相依性測試':537 '固定值':430 '團隊不熟悉':544 '團隊培訓':559 '在實際專案中':352 '基礎':733 '基礎使用':715 '場景':520,535 '大量重複的':301 '天挑戰':766 '太晚凍結了':249 '套件名稱':88 '套件安裝與設定':60 '套件資訊':87 '如':360,489,597 '如尚未安裝':69 '學習成本可能影響開發效率':546 '它':179 '它會自動':124 '它需要接收一個':481 '完整客製化處理範例請參考':499 '完整測試實作範例請參考':515 '官方文件':784 '實作':367,411 '實作類別檔案':743 '實例':210,239,467 '實例作為資料來源提供者':483 '實現自動模擬':11 '將填入測試方法的前幾個參數':431 '將這些替身物件注入到需要的建構函式中':141 '專案名稱':589 '專案特定的':358 '專案特定設定':403 '對象':775 '導入策略':552 '屬性':105,348,351,379,424,588,749 '屬性家族的完整說明':728 '屬性用來控制測試中某個類型的實例':172 '屬性範本':816 '常見相依性的客製化處理':487 '常見陷阱':606 '延伸閱讀':803 '建構函式':384,429 '建構函式變更時':344 '建構函式變更時測試通常不需修改':533 '建構策略':24 '建立':136 '建立包含':150 '建立規範':566 '建議使用的場景':519 '後續在測試方法中都會使用同一個已凍結的實例':180 '從簡單的服務類別開始':555 '必要套件':61 '快速迭代開發':532 '情境':602 '或':591,705 '所有測試都需要修改':300 '手動建立':569 '手動建立可能更清晰直覺':538 '手動建立每個相依性':262 '技能名稱':709 '控制':510 '提升測試維護性':55 '搭配':754 '搭配自訂':747 '效能敏感的測試':549 '效能考量':698 '整合':96,103,771 '整合指南':10 '方式':253,308 '方法':447,601 '明確控制關鍵屬性':675 '時':123,175,218 '替身':357 '最佳實踐':551 '會使用不同的':237 '會使用同一個':200 '會建立這個類別的一個實例並':177 '會自動解析並建立所需的物件':54 '會被凍結':196 '服務層測試':522 '服務層測試完整範例':823 '本技能內容提煉自':763 '本技能的前置知識':716 '某些相依性':488 '核心價值':48 '核心套件':63 '核心概念':116 '模擬框架':111 '機制':22,562 '機制使用模式':820 '正確':221,464 '每個測試方法都會建立新的':699 '沒有':639 '注入相依性':140 '注意事項與限制':605 '涵蓋':19 '涵蓋基本測試':503 '減少手動建立測試資料的工作':531 '減少樣板程式碼':49 '測試實作範例':502 '測試意圖不明確':658 '測試方法':599 '測試方法使用':745 '測試程式碼冗長':304 '測試程式碼通常不需要同步修改':57 '測試資料的控制策略':573 '測試通常不需要修改':345 '漸進式採用':554 '為什麼使用':442 '為什麼需要自訂':349 '物件':17,138 '物件建立的開銷可能影響執行速度':550 '產生':741 '產生自訂':737 '用於結合固定測試值與自動產生物件':412 '用途':89 '當':127 '當參數被標註為':173 '當在':119 '當建構函式變更時':56 '當服務增加新相依性時':299 '當需要自動建立':15 '的':134,756 '的作用':118 '的命名模式':604 '的命名與組織':572 '的客製化範例':498 '的所有介面相依性都會自動變成':163 '的所有設定':486 '的替身':165 '的測試特別重要':183 '的進階用法':722 '相依性已自動建立':322 '相依行為設定':505 '相關套件':68 '相關技能':708 '確保團隊理解':560 '確保整個專案使用相同的設定':365 '確保相同類型的替身在同一個測試中保持一致':144 '程式碼組織':574 '等特殊相依性的客製化處理':28 '範例程式碼':780,811 '簡化複雜相依性注入測試時使用':18 '精確控制屬性值':539 '系列文章':767 '結合固定值與自動產生資料':529 '維持':600 '編譯錯誤或行為異常':463 '繼承自':479 '老派軟體工程師的測試修練':764 '考慮使用':703 '而不是':445 '而應該使用真實實例':493 '自動建立':343,773 '自動建立替身':131 '自動建立服務和其相依性':161 '自動模擬效益最大':524 '自動模擬整合':47 '自動為介面建立':355 '自動產生測試資料':506 '自動產生的物件可能讓除錯變複雜':548 '自動處理多層相依性':527 '自動處理複雜相依圖':52 '自訂':346,570,586,720,814 '與':8,94,758 '衍生類別檔案':739 '複雜物件圖可能增加測試執行時間':702 '複雜相依圖':525 '複雜資料設定':512 '設定':362,543 '設定凍結實例的行為':202 '設定替身行為':284 '設定的詳細說明':735 '說明參數順序的重要性':563 '謹慎使用的場景':534 '讓團隊逐漸熟悉模式':557 '讓開發者專注於測試邏輯而非物件建立':59 '輸出格式':736 '逐步擴展到複雜場景':556 '這個':194 '這對於需要設定相依性行為然後驗證':181 '這樣可以重用':484 '通常有多個相依性':523 '通常需要整合多種客製化設定':353 '連結':91 '進行行為設定與驗證':760 '遇到介面或抽象類別時':129 '過度依賴自動產生':656 '適用場景判斷':518 '遺忘':636 '重要實作細節':441 '錯誤':235,449 '鐵人賽文章':776 '關聯說明':710 '除錯困難的場景':547 '難以快速理解測試意圖':305 '需要':451 '需要大量測試資料':530 '需要額外的':540 '預期':603 '領域模型設定':407 '類別':594 '驗證什麼':674 '驗證器設定等':363","prices":[{"id":"12175318-d1f7-46b4-b42a-1ff3aa897e8e","listingId":"eb78eab2-769b-46c3-9b98-217dc6a4a6e7","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"kevintsengtw","category":"dotnet-testing-agent-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T23:04:25.660Z"}],"sources":[{"listingId":"eb78eab2-769b-46c3-9b98-217dc6a4a6e7","source":"github","sourceId":"kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-autofixture-nsubstitute-integration","sourceUrl":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-autofixture-nsubstitute-integration","isPrimary":false,"firstSeenAt":"2026-04-18T23:04:25.660Z","lastSeenAt":"2026-04-24T13:02:26.368Z"}],"details":{"listingId":"eb78eab2-769b-46c3-9b98-217dc6a4a6e7","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"kevintsengtw","slug":"dotnet-testing-autofixture-nsubstitute-integration","github":{"repo":"kevintsengtw/dotnet-testing-agent-skills","stars":23,"topics":["agent-skills","ai-assisted-development","copilot-skills","csharp","dotnet","dotnet-testing","github-copilot","integration-testing","testing","unit-testing","xunit"],"license":"mit","html_url":"https://github.com/kevintsengtw/dotnet-testing-agent-skills","pushed_at":"2026-03-31T07:28:56Z","description":"AI Agent Skills for .NET Testing - Based on 30-Day Testing Challenge (iThome Ironman 2025 Winner)","skill_md_sha":"a14c3801176b411715d841ac5343e58ef5d61990","skill_md_path":"skills/dotnet-testing-autofixture-nsubstitute-integration/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-autofixture-nsubstitute-integration"},"layout":"multi","source":"github","category":"dotnet-testing-agent-skills","frontmatter":{"name":"dotnet-testing-autofixture-nsubstitute-integration","description":"AutoFixture 與 NSubstitute 整合指南 - 實現自動模擬 (Auto-Mocking)。當需要自動建立 Mock 物件、簡化複雜相依性注入測試時使用。涵蓋 AutoNSubstituteDataAttribute、Frozen 機制、Greedy 建構策略。包含 IMapper (AutoMapper/Mapster) 等特殊相依性的客製化處理。\nMake sure to use this skill whenever the user mentions AutoFixture with NSubstitute, auto-mocking, AutoNSubstituteCustomization, Frozen attribute, or AutoNSubstituteDataAttribute, even if they don't explicitly ask for integration guidance.\nKeywords: autofixture nsubstitute, auto mocking, AutoNSubstituteDataAttribute, 自動模擬, Frozen, AutoNSubstituteCustomization, AutoFixture.AutoNSubstitute, Greedy, fixture.Freeze, Received(), Returns(), IMapper, AutoMapper, Mapster, mapper testing"},"skills_sh_url":"https://skills.sh/kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-autofixture-nsubstitute-integration"},"updatedAt":"2026-04-24T13:02:26.368Z"}}