{"id":"0935fde7-2ad3-44cc-a02e-b67a217bc46e","shortId":"TReheT","kind":"skill","title":"dotnet-testing-advanced-testcontainers-nosql","tagline":"Testcontainers NoSQL 整合測試完整指南。當需要對 MongoDB 或 Redis 進行容器化整合測試時使用。涵蓋 MongoDB 文件操作、Redis 五種資料結構、Collection Fixture 模式。包含 BSON 序列化、索引效能測試、資料隔離策略與容器生命週期管理。\nMake sure to use this skill whenever the user mentions Testcontainers MongoDB, Testcontainers Redis, NoSQL integration test, BSON","description":"# Testcontainers NoSQL 整合測試指南\n\n## 核心概念\n\n### NoSQL 測試的挑戰\n\nNoSQL 資料庫測試與關聯式資料庫有顯著差異：\n\n1. **文件模型複雜度**：MongoDB 支援巢狀物件、陣列、字典等複雜結構\n2. **無固定 Schema**：需要透過測試驗證資料結構的一致性\n3. **多樣化資料結構**：Redis 有五種主要資料結構，各有不同使用場景\n4. **序列化處理**：BSON (MongoDB) 與 JSON (Redis) 序列化行為需要驗證\n\n### Testcontainers 優勢\n\n- **真實環境模擬**：使用實際的 MongoDB 7.0 和 Redis 7.2 容器\n- **一致性測試**：測試結果直接反映正式環境行為\n- **隔離性保證**：每個測試環境完全獨立\n- **效能驗證**：可進行真實的索引效能測試\n\n## 環境需求\n\n### 必要套件\n\n```xml\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <TargetFramework>net9.0</TargetFramework>\n    <Nullable>enable</Nullable>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <IsPackable>false</IsPackable>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <!-- MongoDB 相關套件 -->\n    <PackageReference Include=\"MongoDB.Driver\" Version=\"3.7.1\" />\n    <PackageReference Include=\"MongoDB.Bson\" Version=\"3.7.1\" />\n\n    <!-- Redis 相關套件 -->\n    <PackageReference Include=\"StackExchange.Redis\" Version=\"2.12.8\" />\n\n    <!-- Testcontainers -->\n    <PackageReference Include=\"Testcontainers\" Version=\"4.11.0\" />\n    <PackageReference Include=\"Testcontainers.MongoDb\" Version=\"4.11.0\" />\n    <PackageReference Include=\"Testcontainers.Redis\" Version=\"4.11.0\" />\n\n    <!-- 測試框架 -->\n    <PackageReference Include=\"Microsoft.NET.Test.Sdk\" Version=\"18.3.0\" />\n    <PackageReference Include=\"xunit\" Version=\"2.9.3\" />\n    <PackageReference Include=\"xunit.runner.visualstudio\" Version=\"3.1.5\" />\n    <PackageReference Include=\"AwesomeAssertions\" Version=\"9.4.0\" />\n\n    <!-- JSON 序列化與時間測試 -->\n    <PackageReference Include=\"System.Text.Json\" Version=\"10.0.5\" />\n    <PackageReference Include=\"Microsoft.Bcl.TimeProvider\" Version=\"10.0.5\" />\n    <PackageReference Include=\"Microsoft.Extensions.TimeProvider.Testing\" Version=\"10.4.0\" />\n  </ItemGroup>\n</Project>\n```\n\n### 套件版本說明\n\n| 套件                   | 版本   | 用途                               |\n| ---------------------- | ------ | ---------------------------------- |\n| MongoDB.Driver         | 3.7.1  | MongoDB 官方驅動程式，支援最新功能 |\n| MongoDB.Bson           | 3.7.1  | BSON 序列化處理                    |\n| StackExchange.Redis    | 2.12.8 | Redis 客戶端，支援 Redis 7.x       |\n| Testcontainers.MongoDb | 4.11.0 | MongoDB 容器管理                   |\n| Testcontainers.Redis   | 4.11.0 | Redis 容器管理                     |\n\n---\n\n## MongoDB 容器化測試\n\n涵蓋 MongoDB Container Fixture 建立、複雜文件模型設計（巢狀物件、陣列、字典）、BSON 序列化測試、CRUD 操作測試（含樂觀鎖定）以及索引效能與唯一性約束測試。使用 Collection Fixture 模式共享容器，節省 80% 以上的測試時間。\n\n> 完整程式碼範例請參考 [MongoDB 容器化測試詳細指南](references/mongodb-testing.md)\n\n---\n\n## Redis 容器化測試\n\n涵蓋 Redis Container Fixture 建立、快取模型設計（CacheItem 泛型包裝器、UserSession、RecentView、LeaderboardEntry）以及 Redis 五種資料結構（String、Hash、List、Set、Sorted Set）的完整測試範例，包含 TTL 過期測試與資料隔離策略。\n\n> 完整程式碼範例請參考 [Redis 容器化測試詳細指南](references/redis-testing.md)\n\n---\n\n## 最佳實踐\n\n### 1. Collection Fixture 模式\n\n使用 Collection Fixture 共享容器，避免每個測試重啟容器：\n\n```csharp\n// 定義集合\n[CollectionDefinition(\"MongoDb Collection\")]\npublic class MongoDbCollectionFixture : ICollectionFixture<MongoDbContainerFixture> { }\n\n// 使用集合\n[Collection(\"MongoDb Collection\")]\npublic class MyMongoTests\n{\n    public MyMongoTests(MongoDbContainerFixture fixture)\n    {\n        // 使用共享的容器\n    }\n}\n```\n\n### 2. 資料隔離策略\n\n確保測試間不互相干擾：\n\n```csharp\n// MongoDB：使用唯一的 Email/Username\nvar user = new UserDocument\n{\n    Username = $\"testuser_{Guid.NewGuid():N}\",\n    Email = $\"test_{Guid.NewGuid():N}@example.com\"\n};\n\n// Redis：使用唯一的 Key 前綴\nvar testId = Guid.NewGuid().ToString(\"N\")[..8];\nvar key = $\"test:{testId}:mykey\";\n```\n\n### 3. 清理策略\n\n```csharp\n// MongoDB：測試後清理\nawait fixture.ClearDatabaseAsync();\n\n// Redis：使用 KeyDelete 而非 FLUSHDB（避免權限問題）\nvar keys = server.Keys(database.Database);\nif (keys.Any())\n{\n    await database.KeyDeleteAsync(keys.ToArray());\n}\n```\n\n### 4. 效能考量\n\n| 策略               | 說明                                         |\n| ------------------ | -------------------------------------------- |\n| Collection Fixture | 容器只啟動一次，節省 80%+ 時間               |\n| 資料隔離           | 使用唯一 Key/ID 而非清空資料庫               |\n| 批次操作           | 使用 InsertManyAsync、SetMultipleStringAsync |\n| 索引建立           | 在 Fixture 初始化時建立索引                  |\n\n---\n\n## 常見問題\n\n### Redis FLUSHDB 權限問題\n\n某些 Redis 容器映像檔預設不啟用 admin 模式：\n\n```csharp\n// ❌ 錯誤：可能失敗\nawait server.FlushDatabaseAsync();\n\n// ✅ 正確：使用 KeyDelete\nvar keys = server.Keys(database.Database);\nif (keys.Any())\n{\n    await database.KeyDeleteAsync(keys.ToArray());\n}\n```\n\n### MongoDB 唯一索引重複插入\n\n```csharp\n// 測試時使用唯一的 Email 避免衝突\nvar uniqueEmail = $\"test_{Guid.NewGuid():N}@example.com\";\n```\n\n### 容器啟動超時\n\n```csharp\n// 增加等待時間\n_container = new MongoDbBuilder()\n    .WithImage(\"mongo:7.0\")\n    .WithWaitStrategy(Wait.ForUnixContainer()\n        .UntilCommandIsCompleted(\"mongosh --eval 'db.runCommand({ ping: 1 })'\"))\n    .Build();\n```\n\n---\n\n## 相關技能\n\n- [testcontainers-database](../testcontainers-database/SKILL.md) - PostgreSQL/MSSQL 容器化測試\n- [aspnet-integration-testing](../aspnet-integration-testing/SKILL.md) - ASP.NET Core 整合測試\n- [nsubstitute-mocking](../../dotnet-testing/nsubstitute-mocking/SKILL.md) - 測試替身與 Mock\n- [xunit-upgrade-guide](../dotnet-testing-advanced-xunit-upgrade-guide/SKILL.md) - xUnit v3 升級指南（含 Testcontainers.XunitV3 整合）\n\n---\n\n## 輸出格式\n\n- 產生 Container Fixture 類別（MongoDB/Redis 容器管理）\n- 產生測試類別含 Collection Fixture 設定\n- 提供 .csproj 套件參考配置\n- 包含資料隔離與容器生命週期管理程式碼\n\n## 參考資源\n\n### 原始文章\n\n本技能內容提煉自「老派軟體工程師的測試修練 - 30 天挑戰」系列文章：\n\n- **Day 22 - Testcontainers 整合測試：MongoDB 及 Redis 基礎到進階**\n  - 鐵人賽文章：https://ithelp.ithome.com.tw/articles/10376740\n  - 範例程式碼：https://github.com/kevintsengtw/30Days_in_Testing_Samples/tree/main/day22\n\n### 官方文件\n\n- [Testcontainers 官方網站](https://testcontainers.com/)\n- [.NET Testcontainers 文件](https://dotnet.testcontainers.org/)\n- [MongoDB.Driver 官方文件](https://www.mongodb.com/docs/drivers/csharp/)\n- [StackExchange.Redis 官方文件](https://stackexchange.github.io/StackExchange.Redis/)\n- [xUnit Collection Fixtures](https://xunit.net/docs/shared-context#collection-fixture)","tags":["dotnet","testing","advanced","testcontainers","nosql","agent","skills","kevintsengtw","agent-skills","ai-assisted-development","copilot-skills","csharp"],"capabilities":["skill","source-kevintsengtw","skill-dotnet-testing-advanced-testcontainers-nosql","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-advanced-testcontainers-nosql","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,853 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:25.366Z","embedding":null,"createdAt":"2026-04-18T23:04:17.740Z","updatedAt":"2026-04-24T13:02:25.366Z","lastSeenAt":"2026-04-24T13:02:25.366Z","tsv":"'/)':428,434 '/../dotnet-testing/nsubstitute-mocking/skill.md':371 '/articles/10376740':418 '/aspnet-integration-testing/skill.md':364 '/docs/drivers/csharp/)':439 '/docs/shared-context#collection-fixture)':450 '/dotnet-testing-advanced-xunit-upgrade-guide/skill.md':378 '/kevintsengtw/30days_in_testing_samples/tree/main/day22':422 '/stackexchange.redis/)':444 '/testcontainers-database/skill.md':357 '1':54,188,351 '2':60,218 '2.12.8':114 '22':408 '3':64,253 '3.7.1':105,110 '30':404 '4':69,275 '4.11.0':122,126 '7':119 '7.0':82,343 '7.2':85 '8':247 '80':151,283 'admin':304 'advanc':4 'asp.net':365 'aspnet':361 'aspnet-integration-test':360 'await':258,272,309,320 'bson':24,45,71,111,140 'build':352 'cacheitem':165 'class':203,211 'collect':20,147,189,193,201,207,209,279,393,446 'collectiondefinit':199 'contain':133,161,338,387 'core':366 'crud':142 'csharp':197,221,255,306,325,336 'csproj':397 'databas':356 'database.database':269,317 'database.keydeleteasync':273,321 'day':407 'db.runcommand':349 'dotnet':2 'dotnet-testing-advanced-testcontainers-nosql':1 'dotnet.testcontainers.org':433 'dotnet.testcontainers.org/)':432 'email':233,327 'email/username':224 'enabl':97,98 'eval':348 'example.com':237,334 'fals':99 'fixtur':21,134,148,162,190,194,216,280,295,388,394,447 'fixture.cleardatabaseasync':259 'flushdb':264,299 'github.com':421 'github.com/kevintsengtw/30days_in_testing_samples/tree/main/day22':420 'guid':377 'guid.newguid':231,235,244,332 'hash':174 'icollectionfixtur':205 'insertmanyasync':291 'integr':43,362 'ithelp.ithome.com.tw':417 'ithelp.ithome.com.tw/articles/10376740':416 'json':74 'key':240,249,267,315 'key/id':287 'keydelet':262,313 'keys.any':271,319 'keys.toarray':274,322 'leaderboardentri':169 'list':175 'make':28 'mention':37 'mock':370,373 'mongo':342 'mongodb':11,16,39,56,72,81,106,123,129,132,154,200,208,222,256,323,411 'mongodb.bson':109 'mongodb.driver':104,435 'mongodb/redis':390 'mongodbbuild':340 'mongodbcollectionfixtur':204 'mongodbcontainerfixtur':215 'mongosh':347 'mykey':252 'mymongotest':212,214 'n':232,236,246,333 'net':429 'net9.0':96 'new':227,339 'nosql':6,8,42,47,50,52 'nsubstitut':369 'nsubstitute-mock':368 'ping':350 'postgresql/mssql':358 'public':202,210,213 'recentview':168 'redi':13,18,41,66,75,84,115,118,127,157,160,171,184,238,260,298,302,413 'references/mongodb-testing.md':156 'references/redis-testing.md':186 'schema':62 'server.flushdatabaseasync':310 'server.keys':268,316 'set':176,178 'setmultiplestringasync':292 'skill':33 'skill-dotnet-testing-advanced-testcontainers-nosql' 'sort':177 'source-kevintsengtw' 'stackexchange.github.io':443 'stackexchange.github.io/stackexchange.redis/)':442 'stackexchange.redis':113,440 'string':173 'sure':29 'test':3,44,234,250,331,363 'testcontain':5,7,38,40,46,77,355,409,424,430 'testcontainers-databas':354 'testcontainers.com':427 'testcontainers.com/)':426 'testcontainers.mongodb':121 'testcontainers.redis':125 'testcontainers.xunitv3':383 'testid':243,251 'testus':230 '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' 'tostr':245 'ttl':181 'uniqueemail':330 'untilcommandiscomplet':346 'upgrad':376 'use':31 'user':36,226 'userdocu':228 'usernam':229 'usersess':167 'v3':380 'var':225,242,248,266,314,329 'wait.forunixcontainer':345 'whenev':34 'withimag':341 'withwaitstrategi':344 'www.mongodb.com':438 'www.mongodb.com/docs/drivers/csharp/)':437 'x':120 'xml':95 'xunit':375,379,445 'xunit-upgrade-guid':374 'xunit.net':449 'xunit.net/docs/shared-context#collection-fixture)':448 '一致性測試':87 '五種資料結構':19,172 '以上的測試時間':152 '以及':170 '以及索引效能與唯一性約束測試':145 '使用':146,192,261,290,312 '使用共享的容器':217 '使用唯一':286 '使用唯一的':223,239 '使用實際的':80 '使用集合':206 '優勢':78 '共享容器':195 '初始化時建立索引':296 '前綴':241 '包含':23,180 '包含資料隔離與容器生命週期管理程式碼':399 '升級指南':381 '原始文章':401 '參考資源':400 '及':412 '可能失敗':308 '可進行真實的索引效能測試':92 '各有不同使用場景':68 '含':382 '含樂觀鎖定':144 '和':83 '唯一索引重複插入':324 '在':294 '基礎到進階':414 '增加等待時間':337 '多樣化資料結構':65 '天挑戰':405 '套件':101 '套件參考配置':398 '套件版本說明':100 '字典':139 '字典等複雜結構':59 '完整程式碼範例請參考':153,183 '官方文件':423,436,441 '官方網站':425 '官方驅動程式':107 '定義集合':198 '客戶端':116 '容器':86 '容器化測試':130,158,359 '容器化測試詳細指南':155,185 '容器只啟動一次':281 '容器啟動超時':335 '容器映像檔預設不啟用':303 '容器管理':124,128,391 '巢狀物件':137 '常見問題':297 '序列化':25 '序列化測試':141 '序列化處理':70,112 '序列化行為需要驗證':76 '建立':135,163 '必要套件':94 '快取模型設計':164 '或':12 '批次操作':289 '提供':396 '操作測試':143 '支援':117 '支援巢狀物件':57 '支援最新功能':108 '效能考量':276 '效能驗證':91 '整合':384 '整合測試':367,410 '整合測試完整指南':9 '整合測試指南':48 '文件':431 '文件操作':17 '文件模型複雜度':55 '時間':284 '最佳實踐':187 '有五種主要資料結構':67 '本技能內容提煉自':402 '某些':301 '核心概念':49 '模式':22,191,305 '模式共享容器':149 '權限問題':300 '正確':311 '每個測試環境完全獨立':90 '泛型包裝器':166 '涵蓋':15,131,159 '清理策略':254 '測試後清理':257 '測試時使用唯一的':326 '測試替身與':372 '測試的挑戰':51 '測試結果直接反映正式環境行為':88 '無固定':61 '版本':102 '環境需求':93 '產生':386 '產生測試類別含':392 '用途':103 '當需要對':10 '的完整測試範例':179 '相關技能':353 '真實環境模擬':79 '確保測試間不互相干擾':220 '策略':277 '節省':150,282 '範例程式碼':419 '系列文章':406 '索引建立':293 '索引效能測試':26 '老派軟體工程師的測試修練':403 '而非':263 '而非清空資料庫':288 '與':73 '複雜文件模型設計':136 '設定':395 '說明':278 '資料庫測試與關聯式資料庫有顯著差異':53 '資料隔離':285 '資料隔離策略':219 '資料隔離策略與容器生命週期管理':27 '輸出格式':385 '進行容器化整合測試時使用':14 '過期測試與資料隔離策略':182 '避免權限問題':265 '避免每個測試重啟容器':196 '避免衝突':328 '錯誤':307 '鐵人賽文章':415 '陣列':58,138 '隔離性保證':89 '需要透過測試驗證資料結構的一致性':63 '類別':389","prices":[{"id":"c2564927-5398-4e00-8fad-ee0c2d75b367","listingId":"0935fde7-2ad3-44cc-a02e-b67a217bc46e","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:17.740Z"}],"sources":[{"listingId":"0935fde7-2ad3-44cc-a02e-b67a217bc46e","source":"github","sourceId":"kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-advanced-testcontainers-nosql","sourceUrl":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-advanced-testcontainers-nosql","isPrimary":false,"firstSeenAt":"2026-04-18T23:04:17.740Z","lastSeenAt":"2026-04-24T13:02:25.366Z"}],"details":{"listingId":"0935fde7-2ad3-44cc-a02e-b67a217bc46e","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"kevintsengtw","slug":"dotnet-testing-advanced-testcontainers-nosql","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":"7abac2ea57e932a314103118cac35a0f77c8eca0","skill_md_path":"skills/dotnet-testing-advanced-testcontainers-nosql/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-advanced-testcontainers-nosql"},"layout":"multi","source":"github","category":"dotnet-testing-agent-skills","frontmatter":{"name":"dotnet-testing-advanced-testcontainers-nosql","description":"Testcontainers NoSQL 整合測試完整指南。當需要對 MongoDB 或 Redis 進行容器化整合測試時使用。涵蓋 MongoDB 文件操作、Redis 五種資料結構、Collection Fixture 模式。包含 BSON 序列化、索引效能測試、資料隔離策略與容器生命週期管理。\nMake sure to use this skill whenever the user mentions Testcontainers MongoDB, Testcontainers Redis, NoSQL integration test, BSON serialization, or Redis data structure testing, even if they don't explicitly ask for NoSQL container testing.\nKeywords: testcontainers mongodb, testcontainers redis, mongodb integration test, redis integration test, nosql testing, MongoDbContainer, RedisContainer, IMongoDatabase, IConnectionMultiplexer, BSON serialization, BsonDocument, 文件模型測試, 快取測試, Collection Fixture"},"skills_sh_url":"https://skills.sh/kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-advanced-testcontainers-nosql"},"updatedAt":"2026-04-24T13:02:25.366Z"}}