我正在尝试启动一个 TestContainer 实例,为每个测试类创建 sql server。然后在每次测试之前创建并迁移一个新数据库,并在删除每个测试数据库之后。
TestContainer 夹具是使用 IAsyncLifetime 定义的,测试类也是如此,因为它们依赖于异步方法。
TestClass 使用 IClassFixture 为每个类定义单个 TestContainerFixture。这似乎工作正常,因为 TestContainerFixtures
InitializeAsync()
只被调用一次。
TestClass 还使用 IAsyncLifetime,并且 TestClasses
InitializeAsync()
在每次测试之前运行。这是可行的,但问题是我无法创建具有唯一名称的数据库,因为 Guid.NewGuid().ToString()
总是返回相同的结果。这是为什么?我是否缺少一些有关 xunit/.net-core 如何处理并行测试/线程的重要信息?
测试课是这样的:
public class TestClass: IClassFixture<TestContainerFixture>, IAsyncLifetime
{
private readonly TestContainerFixture _testContainerFixture;
public TestClass(TestContainerFixture fixture)
{
_testContainerFixture = fixture;
}
public async Task InitializeAsync()
{
// this guid will always be identical, that is the main problem
var guid = Guid.NewGuid().ToString();
var data = await _testContainerFixture.SetupDatabaseAsync(guid);
}
public async Task DisposeAsync()
{
await _testContainerFixture.DropDatabaseAsync();
}
}
TestContainerFixture 定义如下:
public class TestContainerFixture : IAsyncLifetime
{
private string _databaseName { get; set; } = String.Empty;
private string _connectionString { get; set; } = String.Empty;
private MsSqlContainer _databaseContainer { get; set; } = default!;
public TestContainerFixture()
{
}
public virtual async Task InitializeAsync()
{
_databaseContainer = new MsSqlBuilder()
.WithAutoRemove(autoRemove: true)
.WithExposedPort(54465)
.Build();
await _databaseContainer.StartAsync();
}
public async Task<(IOptionsMonitor<Config>, IUnitOfWork)> SetupDatabaseAsync(string dbname)
{
_databaseName = dbname;
// this commented out code also produces identical guids between tests
//_databaseName = "Test" + Guid.NewGuid().ToString().Replace("-", "");
await _databaseContainer.ExecScriptAsync($"create database [{dbname}]");
_connectionString = _databaseContainer.GetConnectionString().Replace("Database=master", $"Database={dbname}");
}
public async Task DisposeAsync() => await _databaseContainer.StopAsync();
}
好吧,我明白了。也许当我说出这个问题时,突然想到了什么。解决方案是从 TestContainerFixture 属性中删除databaseName和connectionString,并将它们作为参数从TestClass IAsyncLifeTime一直传递。也许 TestClass 根本没有创建相同的 guid,也许我很困惑,因为 TestContainerFixture 只有一个实例并且私有属性没有更新。我使用 ITestOutputHelper 来解决这个问题。
有时必须再次测试一下,但现在可以了。