SuperAPI AI Directory

dotnet-testing-advanced-testcontainers-nosql

Data & analytics

View repository

Updated 10-16 06:22

About this skill

Testcontainers NoSQL Integration Testing Guide

Core Concepts

Challenges of NoSQL Testing

NoSQL database testing differs significantly from relational database testing:

  1. Document model complexity: MongoDB supports complex structures such as nested objects, arrays, and dictionaries
  2. No fixed schema: Data structure consistency needs to be verified through tests
  3. Diverse data structures: Redis has five main data structures, each with different use cases
  4. Serialization handling: BSON (MongoDB) and JSON (Redis) serialization behavior needs to be verified

Advantages of Testcontainers

  • Real environment simulation: Uses actual MongoDB 7.0 and Redis 7.2 containers
  • Consistency testing: Test results directly reflect production environment behavior
  • Isolation guarantee: Each test environment is completely independent
  • Performance verification: Enables real index performance testing

Environment Requirements

Required Packages

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <IsPackable>false</IsPackable>
  </PropertyGroup>

  <ItemGroup>
    <!-- MongoDB 相關套件 -->
    <PackageReference Include="MongoDB.Driver" Version="3.7.1" />
    <PackageReference Include="MongoDB.Bson" Version="3.7.1" />

    <!-- Redis 相關套件 -->
    <PackageReference Include="StackExchange.Redis" Version="2.12.8" />

    <!-- Testcontainers -->
    <PackageReference Include="Testcontainers" Version="4.11.0" />
    <PackageReference Include="Testcontainers.MongoDb" Version="4.11.0" />
    <PackageReference Include="Testcontainers.Redis" Version="4.11.0" />

    <!-- 測試框架 -->
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
    <PackageReference Include="xunit" Version="2.9.3" />
    <PackageReference Include="xunit.runner.visualstudio" Version="3.1.5" />
    <PackageReference Include="AwesomeAssertions" Version="9.4.0" />

    <!-- JSON 序列化與時間測試 -->
    <PackageReference Include="System.Text.Json" Version="10.0.5" />
    <PackageReference Include="Microsoft.Bcl.TimeProvider" Version="10.0.5" />
    <PackageReference Include="Microsoft.Extensions.TimeProvider.Testing" Version="10.4.0" />
  </ItemGroup>
</Project>

Package Version Description

Package Version Purpose
MongoDB.Driver 3.7.1 MongoDB official driver, supports the latest features
MongoDB.Bson 3.7.1 BSON serialization handling
StackExchange.Redis 2.12.8 Redis client, supports Redis 7.x
Testcontainers.MongoDb 4.11.0 MongoDB container management
Testcontainers.Redis 4.11.0 Redis container management

MongoDB Containerized Testing

Covers MongoDB Container Fixture setup, complex document model design (nested objects, arrays, dictionaries), BSON serialization testing, CRUD operation testing (including optimistic locking), and index performance and uniqueness constraint testing. Uses the Collection Fixture pattern to share containers, saving more than 80% of testing time.

For complete code examples, refer to Detailed Guide to MongoDB Containerized Testing


Redis Containerized Testing

Covers Redis Container Fixture setup, cache model design (CacheItem generic wrapper, UserSession, RecentView, LeaderboardEntry), and complete test examples for Redis's five data structures (String, Hash, List, Set, Sorted Set), including TTL expiration testing and data isolation strategies.

For complete code examples, refer to Detailed Guide to Redis Containerized Testing


Best Practices

1. Collection Fixture Pattern

Use Collection Fixture to share containers and avoid restarting containers for each test:

// 定義集合
[CollectionDefinition("MongoDb Collection")]
public class MongoDbCollectionFixture : ICollectionFixture<MongoDbContainerFixture> { }

// 使用集合
[Collection("MongoDb Collection")]
public class MyMongoTests
{
    public MyMongoTests(MongoDbContainerFixture fixture)
    {
        // 使用共享的容器
    }
}

2. Data Isolation Strategy

Ensure tests do not interfere with each other:

// MongoDB:使用唯一的 Email/Username
var user = new UserDocument
{
    Username = $"testuser_{Guid.NewGuid():N}",
    Email = $"test_{Guid.NewGuid():N}@example.com"
};

// Redis:使用唯一的 Key 前綴
var testId = Guid.NewGuid().ToString("N")[..8];
var key = $"test:{testId}:mykey";

3. Cleanup Strategy

// MongoDB:測試後清理
await fixture.ClearDatabaseAsync();

// Redis:使用 KeyDelete 而非 FLUSHDB(避免權限問題)
var keys = server.Keys(database.Database);
if (keys.Any())
{
    await database.KeyDeleteAsync(keys.ToArray());
}

4. Performance Considerations

Strategy Description
Collection Fixture The container starts only once, saving 80%+ of time
Data isolation Use unique Keys/IDs instead of clearing the database
Batch operations Use InsertManyAsync, SetMultipleStringAsync
Index creation Create indexes during Fixture initialization

Frequently Asked Questions

Redis FLUSHDB Permission Issue

Some Redis container images do not enable admin mode by default:

// ❌ 錯誤:可能失敗
await server.FlushDatabaseAsync();

// ✅ 正確:使用 KeyDelete
var keys = server.Keys(database.Database);
if (keys.Any())
{
    await database.KeyDeleteAsync(keys.ToArray());
}

MongoDB Unique Index Duplicate Insert

// 測試時使用唯一的 Email 避免衝突
var uniqueEmail = $"test_{Guid.NewGuid():N}@example.com";

Container Startup Timeout

// 增加等待時間
_container = new MongoDbBuilder()
    .WithImage("mongo:7.0")
    .WithWaitStrategy(Wait.ForUnixContainer()
        .UntilCommandIsCompleted("mongosh --eval 'db.runCommand({ ping: 1 })'"))
    .Build();

Related Skills


Output Format

  • Generate Container Fixture class (MongoDB/Redis container management)
  • Generate test classes with Collection Fixture configuration
  • Provide .csproj package reference configuration
  • Include data isolation and container lifecycle management code

Reference Resources

Original Articles

The content of this skill is distilled from the "Old-School Software Engineer's Testing Practice - 30-Day Challenge" series of articles:

Official Documentation