You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NUnit中为TestContainers配置全局OneTimeSetup和OneTimeTearDown?

在NUnit中实现TestContainers MongoDB容器全局复用

问题场景

我在.NET测试中尝试结合TestContainers与NUnit使用,现有两个测试用例,每个测试都会重复创建、启动MongoDB容器,用完后销毁,总执行时间约9秒。这些测试均继承自一个基类,基类通过OneTimeSetUp和OneTimeTearDown管理容器生命周期:

[OneTimeSetUp]
public async Task OneTimeSetup()
{
    _testContainer = new MongoDbBuilder().Build();
    await _testContainer.StartAsync();

    _client = new MongoClient(_testContainer.GetConnectionString());
    Database = _client.GetDatabase("test");
}

[OneTimeTearDown]
public async Task OneTimeTeardown() => await _testContainer.DisposeAsync();

当前每个测试类都会重复执行容器的创建和销毁逻辑,我希望实现全局复用容器的执行流程:

Global Setup <==== 在此启动容器
Test1 Setup <---- 使用已创建的容器
Test1 Run
Test1 Teardown

Test2 Setup  <---- 使用同一容器
Test2 Run
Test2 Teardown

Global Teardown <==== 在此销毁容器

请问能否通过NUnit实现该需求?


解决方案:用NUnit的[SetUpFixture]实现全局容器生命周期管理

当然可以实现,核心是使用NUnit的[SetUpFixture]特性定义全局初始化和清理逻辑,替代原基类中每个测试类执行一次的OneTimeSetUp/OneTimeTearDown。

步骤1:创建全局SetUpFixture类

在测试项目的根命名空间下创建一个标记[SetUpFixture]的类,统一管理MongoDB容器的全局生命周期:

using NUnit.Framework;
using TestContainers.MongoDb;
using MongoDB.Driver;

[SetUpFixture]
public class GlobalTestSetup
{
    public static MongoDbContainer? TestContainer { get; private set; }
    public static IMongoDatabase? TestDatabase { get; private set; }

    [OneTimeSetUp]
    public async Task GlobalSetup()
    {
        // 全局启动一次MongoDB容器
        TestContainer = new MongoDbBuilder().Build();
        await TestContainer.StartAsync();

        var client = new MongoClient(TestContainer.GetConnectionString());
        TestDatabase = client.GetDatabase("test");
    }

    [OneTimeTearDown]
    public async Task GlobalTeardown()
    {
        // 全局销毁一次容器
        if (TestContainer != null)
        {
            await TestContainer.DisposeAsync();
        }
    }
}

步骤2:修改测试基类

原测试基类无需再管理容器生命周期,直接引用全局类的静态属性即可,同时可在[SetUp]中清理集合数据保证测试隔离:

using NUnit.Framework;
using MongoDB.Driver;

public class MongoTestBase
{
    protected IMongoDatabase Database => GlobalTestSetup.TestDatabase!;

    [SetUp]
    public void TestSetup()
    {
        // 每个测试前清理集合,避免测试间数据污染
        foreach (var collectionName in Database.ListCollectionNames().ToList())
        {
            Database.DropCollection(collectionName);
        }
    }
}

步骤3:编写测试类

测试类只需继承基类,正常编写测试逻辑即可,无需关心容器的创建与销毁:

using NUnit.Framework;
using MongoDB.Driver;

[TestFixture]
public class FirstMongoTests : MongoTestBase
{
    [Test]
    public async Task Test1_InsertDocument()
    {
        var collection = Database.GetCollection<MyDocument>("docs");
        await collection.InsertOneAsync(new MyDocument { Name = "Test1" });
        var count = await collection.CountDocumentsAsync(_ => true);
        Assert.That(count, Is.EqualTo(1));
    }
}

[TestFixture]
public class SecondMongoTests : MongoTestBase
{
    [Test]
    public async Task Test2_QueryDocument()
    {
        var collection = Database.GetCollection<MyDocument>("docs");
        await collection.InsertOneAsync(new MyDocument { Name = "Test2" });
        var doc = await collection.Find(_ => _.Name == "Test2").FirstOrDefaultAsync();
        Assert.That(doc, Is.Not.Null);
    }
}

public class MyDocument
{
    public string Name { get; set; } = string.Empty;
}

关键说明

  • [SetUpFixture]的OneTimeSetUp会在所有测试开始前执行一次,OneTimeTearDown会在所有测试结束后执行一次,完全匹配全局容器的生命周期需求。
  • 每个测试前的[SetUp]清理集合数据,能保证测试用例之间的独立性,避免数据互相干扰。
  • 整个测试套件仅会启动和销毁一次MongoDB容器,可大幅缩短总执行时间。

内容的提问来源于stack exchange,提问作者napfernandes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 11:05:09