{"id":"29dedac1-26e6-4364-aed8-bc9546e242ab","shortId":"DNnuVU","kind":"skill","title":"dotnet-testing-autofixture-basics","tagline":"使用 AutoFixture 自動產生測試資料的基礎技能。當需要快速產生測試物件、減少樣板程式碼、實現匿名測試時使用。涵蓋 Fixture.Create、CreateMany、循環參考處理、與 xUnit 整合等。\nMake sure to use this skill whenever the user mentions AutoFixture, fixture.Create, anonymous testing, auto-generating test data, or reducing test boilerplate, even if they","description":"# AutoFixture 基礎：自動產生測試資料\n\n## 安裝套件\n\n```xml\n<PackageReference Include=\"AutoFixture\" Version=\"4.18.1\" />\n<PackageReference Include=\"AutoFixture.Xunit2\" Version=\"4.18.1\" />\n```\n\n或透過命令列安裝：\n\n```powershell\ndotnet add package AutoFixture\ndotnet add package AutoFixture.Xunit2\n```\n\n## 核心 API 摘要\n\n| API                      | 用途                         | 預設行為              |\n| ------------------------ | ---------------------------- | --------------------- |\n| `fixture.Create<T>()`   | 產生單一物件                 | 自動填充所有屬性      |\n| `fixture.CreateMany<T>()` | 產生集合                   | 預設 3 個元素         |\n| `fixture.Build<T>()`    | 精確控制屬性                 | 搭配 With/Without     |\n| `OmitAutoProperties()`  | 只設定必要屬性               | 其餘保持預設值        |\n\n### 基本使用\n\n`Fixture` 是核心類別，提供自動產生測試資料的能力：\n\n- **基本型別**：`int`（隨機正整數）、`string`（GUID 格式）、`decimal`、`bool`、`DateTime`、`Guid`\n- **複雜物件**：自動建構巢狀物件與集合屬性，所有層級的屬性都會自動填入值\n- **集合產生**：`CreateMany<T>()` 預設產生 3 個元素，可指定數量如 `CreateMany<T>(10)`\n\n> 完整程式碼範例請參考 [references/basic-usage-examples.md](references/basic-usage-examples.md)\n\n### Build<T>() 精確控制\n\n當需要對特定屬性進行控制時，使用 `Build<T>()` 模式：\n\n| 方法                    | 用途                         | 範例                                       |\n| ----------------------- | ---------------------------- | ------------------------------------------ |\n| `.With(prop, value)`    | 指定固定值                   | `.With(x => x.Name, \"測試客戶\")`           |\n| `.With(prop, factory)`  | 使用工廠方法產生值           | `.With(x => x.Price, () => random.Next())` |\n| `.Without(prop)`        | 排除屬性，保持預設值         | `.Without(x => x.InternalId)`              |\n| `.OmitAutoProperties()` | 不自動設定任何屬性          | 只設定關心的屬性                           |\n\n### 循環參考處理\n\n當物件包含循環參考時（如 Category 的 Parent 屬性指向自己），AutoFixture 預設會拋出 `ObjectCreationException`。\n\n**解決方案：** 使用 `OmitOnRecursionBehavior`，移除預設的 `ThrowingRecursionBehavior` 並加入忽略循環參考的行為。\n\n**建議：** 建立 `AutoFixtureTestBase` 基底類別統一處理循環參考，避免在每個測試中重複設定。\n\n> 完整程式碼範例請參考 [references/build-and-customization.md](references/build-and-customization.md)\n\n## xUnit 整合\n\n### Fixture 共享客製化\n\n在測試類別建構函式中使用 `Customize<T>()` 設定共用的資料產生規則，所有測試方法共享同一個 Fixture 設定。\n\n### 結合 Theory 測試\n\n搭配 `[Theory]` + `[InlineData]`，使用 `Build<T>().With()` 針對不同輸入情境設定關鍵屬性值，驗證各情境的預期行為。\n\n### 匿名測試原則\n\n測試應該關注「行為」而不是「資料」：\n\n- **好的做法：** 使用 `fixture.Create<T>()` 產生任意有效資料，驗證操作結果\n- **避免：** 依賴隨機產生值的具體內容（如假設年齡大於 18）\n- **正確：** 使用 `Build<T>().With()` 明確設定影響測試結果的關鍵值\n\n> 完整程式碼範例請參考 [references/xunit-integration-examples.md](references/xunit-integration-examples.md)\n\n## 進化比較：Test Data Builder vs AutoFixture\n\n| 層面       | Test Data Builder      | AutoFixture        |\n| ---------- | ---------------------- | ------------------ |\n| 程式碼行數 | 40+ 行 Builder + 測試  | 5 行測試           |\n| 維護成本   | 物件改變需更新 Builder | 自動適應變化       |\n| 開發時間   | 先寫 Builder 再寫測試  | 直接寫測試         |\n| 大量資料   | 需要迴圈               | `CreateMany(100)`  |\n| 可讀性     | 業務語意明確           | 需理解 AutoFixture |\n\n> 完整比較程式碼與混合策略請參考 [references/xunit-integration-examples.md](references/xunit-integration-examples.md)\n\n## 混合策略建議\n\n結合 Test Data Builder 與 AutoFixture 的優點：\n\n- 使用 AutoFixture 建立基礎資料，再用 Builder 加工\n- 使用 `TestDataFactory` 封裝常用的資料產生模式\n- 大量隨機資料產生使用 `CreateMany<T>(count)`\n\n> 完整比較程式碼與混合策略請參考 [references/xunit-integration-examples.md](references/xunit-integration-examples.md)\n\n## 實務應用場景\n\nAutoFixture 在實務中常用於以下場景：\n\n- **Entity 測試**：搭配 Theory 驗證不同輸入場景\n- **DTO 驗證**：使用 `Build<T>()` 產生符合驗證規則的資料\n- **大量資料測試**：使用 `CreateMany()` 產生批次資料\n- **服務層測試**：搭配 NSubstitute 自動產生 Mock 參數\n\n> 完整程式碼範例請參閱 [references/practical-scenarios.md](references/practical-scenarios.md)\n\n## 常見問題\n\n### Q1: 何時該用 AutoFixture，何時該用固定值？\n\n- **用 AutoFixture**：不影響測試結果的「填充」資料，如使用者的 Email、地址等\n- **用固定值**：影響測試邏輯的「關鍵」資料，如折扣計算中的客戶類型、年齡驗證中的年齡值\n\n### Q2: CreateMany 預設產生幾個？如何調整？\n\n預設產生 3 個元素，可透過參數指定數量：`fixture.CreateMany<T>(10)`。若要全域調整，使用 `fixture.RepeatCount = 5`。\n\n### Q3: AutoFixture 產生的字串格式不符合需求？\n\n使用 `Build<T>().With()` 指定格式，或搭配 `Customize<T>()` 設定全域規則。若需要真實感資料，考慮整合 Bogus。\n\n## 最佳實踐\n\n### 應該做\n\n1. **使用匿名測試概念** — 專注於測試邏輯而非具體資料\n2. **只在必要時固定特定值** — 使用 `Build<T>().With()` 設定關鍵屬性\n3. **建立共用基底類別** — 統一處理循環參考等共同配置\n4. **合理的集合大小** — 根據測試目的調整 `CreateMany()` 數量\n\n### 應該避免\n\n1. **過度依賴隨機值** — 不要假設隨機值的具體內容\n2. **忽略邊界值** — 仍需要明確測試邊界情況\n3. **濫用自動產生** — 簡單測試可能用固定值更清楚\n\n## 程式碼範本\n\n請參考 [templates](./templates) 資料夾中的範例檔案：\n\n- [basic-autofixture-usage.cs](./templates/basic-autofixture-usage.cs) - 基本使用方式\n- [complex-object-scenarios.cs](./templates/complex-object-scenarios.cs) - 複雜物件與循環參考\n- [xunit-integration.cs](./templates/xunit-integration.cs) - xUnit 整合與 Theory 測試\n\n## 輸出格式\n\n- 產生使用 AutoFixture 的測試類別（.cs 檔案）\n- 包含 Fixture.Create/CreateMany/Build 用法範例\n- 提供 .csproj 套件參考（AutoFixture、AutoFixture.Xunit2）\n- 包含循環參考處理與自訂行為設定\n\n## 參考資源\n\n### 原始文章\n\n- **Day 10 - AutoFixture 基礎：自動產生測試資料**\n  - 鐵人賽文章：https://ithelp.ithome.com.tw/articles/10375018\n  - 範例程式碼：https://github.com/kevintsengtw/30Days_in_Testing_Samples/tree/main/day10\n\n### 官方文件\n\n- [AutoFixture GitHub](https://github.com/AutoFixture/AutoFixture)\n- [AutoFixture 官方網站](https://autofixture.github.io/)\n- [AutoFixture 快速入門](https://autofixture.github.io/docs/quick-start/)\n\n### 相關技能\n\n- `dotnet-testing-autofixture-customization` - AutoFixture 進階自訂\n- `dotnet-testing-autofixture-bogus-integration` - AutoFixture + Bogus 整合\n- `dotnet-testing-autofixture-nsubstitute-integration` - AutoFixture + NSubstitute 整合\n- `dotnet-testing-autodata-xunit-integration` - AutoData 與 xUnit 整合\n- `dotnet-testing-test-data-builder-pattern` - Test Data Builder Pattern","tags":["dotnet","testing","autofixture","basics","agent","skills","kevintsengtw","agent-skills","ai-assisted-development","copilot-skills","csharp","dotnet-testing"],"capabilities":["skill","source-kevintsengtw","skill-dotnet-testing-autofixture-basics","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-basics","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 (5,417 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.098Z","embedding":null,"createdAt":"2026-04-18T23:04:23.301Z","updatedAt":"2026-04-24T13:02:26.098Z","lastSeenAt":"2026-04-24T13:02:26.098Z","tsv":"'/)':432 '/articles/10375018':417 '/autofixture/autofixture)':427 '/createmany/build':399 '/docs/quick-start/)':437 '/kevintsengtw/30days_in_testing_samples/tree/main/day10':421 '/templates':376 '/templates/basic-autofixture-usage.cs':379 '/templates/complex-object-scenarios.cs':382 '/templates/xunit-integration.cs':385 '1':346,364 '10':105,326,410 '100':241 '18':202 '2':349,367 '3':72,101,322,355,370 '4':358 '40':223 '5':227,330 'add':53,57 'anonym':31 'api':61,63 'auto':34 'auto-gener':33 'autodata':467,470 'autofixtur':4,7,29,45,55,151,216,221,245,255,258,273,301,304,332,392,404,411,423,428,433,442,444,449,452,458,461 'autofixture.github.io':431,436 'autofixture.github.io/)':430 'autofixture.github.io/docs/quick-start/)':435 'autofixture.xunit2':59,405 'autofixturetestbas':162 'basic':5 'basic-autofixture-usage.cs':378 'bogus':343,450,453 'boilerpl':41 'bool':92 'build':109,113,185,205,283,335,352 'builder':214,220,225,231,235,253,261,479,483 'categori':147 'complex-object-scenarios.cs':381 'count':268 'createmani':14,99,104,240,267,287,318,361 'cs':394 'csproj':402 'custom':173,339,443 'data':37,213,219,252,478,482 'datetim':93 'day':409 'decim':91 'dotnet':2,52,56,440,447,456,465,475 'dotnet-testing-autodata-xunit-integr':464 'dotnet-testing-autofixture-bas':1 'dotnet-testing-autofixture-bogus-integr':446 'dotnet-testing-autofixture-custom':439 'dotnet-testing-autofixture-nsubstitute-integr':455 'dotnet-testing-test-data-builder-pattern':474 'dto':280 'email':309 'entiti':275 'even':42 'factori':128 'fixtur':82,170,176 'fixture.build':74 'fixture.create':13,30,66,196,398 'fixture.create/createmany/build':397 'fixture.createmany':69,325 'fixture.repeatcount':329 'generat':35 'github':424 'github.com':420,426 'github.com/autofixture/autofixture)':425 'github.com/kevintsengtw/30days_in_testing_samples/tree/main/day10':419 'guid':89,94 'inlinedata':183 'int':86 'integr':451,460,469 'ithelp.ithome.com.tw':416 'ithelp.ithome.com.tw/articles/10375018':415 'make':19 'mention':28 'mock':293 'nsubstitut':291,459,462 'objectcreationexcept':153 'omitautoproperti':78,141 'omitonrecursionbehavior':156 'packag':54,58 'parent':149 'pattern':480,484 'powershel':51 'prop':119,127,135 'q1':299 'q2':317 'q3':331 'random.next':133 'reduc':39 'references/basic-usage-examples.md':107,108 'references/build-and-customization.md':166,167 'references/practical-scenarios.md':296,297 'references/xunit-integration-examples.md':209,210,247,248,270,271 'skill':24 'skill-dotnet-testing-autofixture-basics' 'source-kevintsengtw' 'string':88 'sure':20 'templat':375 'test':3,32,36,40,212,218,251,441,448,457,466,476,477,481 'testdatafactori':264 'theori':179,182,278,388 'throwingrecursionbehavior':158 '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' 'use':22 'user':27 'valu':120 'vs':215 'whenev':25 'with/without':77 'without':134,138 'x':123,131,139 'x.internalid':140 'x.name':124 'x.price':132 'xml':49 'xunit':17,168,386,468,472 'xunit-integration.cs':384 '不影響測試結果的':305 '不自動設定任何屬性':142 '不要假設隨機值的具體內容':366 '並加入忽略循環參考的行為':159 '仍需要明確測試邊界情況':369 '何時該用':300 '何時該用固定值':302 '使用':6,112,155,184,195,204,257,263,282,286,328,334,351 '使用匿名測試概念':347 '使用工廠方法產生值':129 '依賴隨機產生值的具體內容':200 '保持預設值':137 '個元素':73,102,323 '先寫':234 '共享客製化':171 '其餘保持預設值':80 '再寫測試':236 '再用':260 '加工':262 '包含':396 '包含循環參考處理與自訂行為設定':406 '匿名測試原則':189 '原始文章':408 '參數':294 '參考資源':407 '只在必要時固定特定值':350 '只設定必要屬性':79 '只設定關心的屬性':143 '可指定數量如':103 '可讀性':242 '可透過參數指定數量':324 '合理的集合大小':359 '在實務中常用於以下場景':274 '在測試類別建構函式中使用':172 '地址等':310 '基底類別統一處理循環參考':163 '基本使用':81 '基本使用方式':380 '基本型別':85 '基礎':46,412 '填充':306 '大量資料':238 '大量資料測試':285 '大量隨機資料產生使用':266 '套件參考':403 '好的做法':194 '如':146 '如何調整':320 '如使用者的':308 '如假設年齡大於':201 '如折扣計算中的客戶類型':315 '安裝套件':48 '完整比較程式碼與混合策略請參考':246,269 '完整程式碼範例請參考':106,165,208 '完整程式碼範例請參閱':295 '官方文件':422 '官方網站':429 '實務應用場景':272 '實現匿名測試時使用':11 '封裝常用的資料產生模式':265 '專注於測試邏輯而非具體資料':348 '層面':217 '屬性指向自己':150 '常見問題':298 '年齡驗證中的年齡值':316 '建立':161 '建立共用基底類別':356 '建立基礎資料':259 '建議':160 '影響測試邏輯的':312 '循環參考處理':15,144 '快速入門':434 '忽略邊界值':368 '應該做':345 '應該避免':363 '或搭配':338 '或透過命令列安裝':50 '所有層級的屬性都會自動填入值':97 '所有測試方法共享同一個':175 '指定固定值':121 '指定格式':337 '排除屬性':136 '提供':401 '提供自動產生測試資料的能力':84 '搭配':76,181,277,290 '摘要':62 '整合':169,454,463,473 '整合等':18 '整合與':387 '數量':362 '方法':115 '明確設定影響測試結果的關鍵值':207 '是核心類別':83 '最佳實踐':344 '服務層測試':289 '核心':60 '根據測試目的調整':360 '格式':90 '業務語意明確':243 '模式':114 '檔案':395 '正確':203 '涵蓋':12 '混合策略建議':249 '減少樣板程式碼':10 '測試':180,226,276,389 '測試客戶':125 '測試應該關注':190 '濫用自動產生':371 '物件改變需更新':230 '產生任意有效資料':197 '產生使用':391 '產生單一物件':67 '產生批次資料':288 '產生的字串格式不符合需求':333 '產生符合驗證規則的資料':284 '產生集合':70 '用':303 '用固定值':311 '用法範例':400 '用途':64,116 '當物件包含循環參考時':145 '當需要對特定屬性進行控制時':111 '當需要快速產生測試物件':9 '的':148 '的優點':256 '的測試類別':393 '直接寫測試':237 '相關技能':438 '移除預設的':157 '程式碼範本':373 '程式碼行數':222 '範例':117 '範例程式碼':418 '簡單測試可能用固定值更清楚':372 '精確控制':110 '精確控制屬性':75 '結合':178,250 '統一處理循環參考等共同配置':357 '維護成本':229 '考慮整合':342 '而不是':192 '自動填充所有屬性':68 '自動建構巢狀物件與集合屬性':96 '自動產生':292 '自動產生測試資料':47,413 '自動產生測試資料的基礎技能':8 '自動適應變化':232 '與':16,254,471 '若要全域調整':327 '若需要真實感資料':341 '行':224 '行測試':228 '行為':191 '複雜物件':95 '複雜物件與循環參考':383 '解決方案':154 '設定':177 '設定全域規則':340 '設定共用的資料產生規則':174 '設定關鍵屬性':354 '請參考':374 '資料':193,307,314 '資料夾中的範例檔案':377 '輸出格式':390 '進化比較':211 '進階自訂':445 '過度依賴隨機值':365 '避免':199 '避免在每個測試中重複設定':164 '針對不同輸入情境設定關鍵屬性值':187 '鐵人賽文章':414 '開發時間':233 '關鍵':313 '隨機正整數':87 '集合產生':98 '需理解':244 '需要迴圈':239 '預設':71 '預設會拋出':152 '預設產生':100,321 '預設產生幾個':319 '預設行為':65 '驗證':281 '驗證不同輸入場景':279 '驗證各情境的預期行為':188 '驗證操作結果':198","prices":[{"id":"33c325d3-4db0-4a16-82ec-4b50f78d3f85","listingId":"29dedac1-26e6-4364-aed8-bc9546e242ab","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:23.301Z"}],"sources":[{"listingId":"29dedac1-26e6-4364-aed8-bc9546e242ab","source":"github","sourceId":"kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-autofixture-basics","sourceUrl":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-autofixture-basics","isPrimary":false,"firstSeenAt":"2026-04-18T23:04:23.301Z","lastSeenAt":"2026-04-24T13:02:26.098Z"}],"details":{"listingId":"29dedac1-26e6-4364-aed8-bc9546e242ab","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"kevintsengtw","slug":"dotnet-testing-autofixture-basics","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":"250fee801c3d2aecf61e99f3d6c15fee9c811c99","skill_md_path":"skills/dotnet-testing-autofixture-basics/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-autofixture-basics"},"layout":"multi","source":"github","category":"dotnet-testing-agent-skills","frontmatter":{"name":"dotnet-testing-autofixture-basics","description":"使用 AutoFixture 自動產生測試資料的基礎技能。當需要快速產生測試物件、減少樣板程式碼、實現匿名測試時使用。涵蓋 Fixture.Create、CreateMany、循環參考處理、與 xUnit 整合等。\nMake sure to use this skill whenever the user mentions AutoFixture, fixture.Create, anonymous testing, auto-generating test data, or reducing test boilerplate, even if they don't explicitly ask for AutoFixture guidance.\nKeywords: autofixture, fixture, 自動產生測試資料, test data generation, anonymous testing, 匿名測試, fixture.Create, CreateMany, fixture.Build, Create<T>, AutoFixture.Xunit2, OmitOnRecursionBehavior, IFixture, 產生測試資料, generate test data"},"skills_sh_url":"https://skills.sh/kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-autofixture-basics"},"updatedAt":"2026-04-24T13:02:26.098Z"}}