我想做的是使用Entity Framework为微服务环境编写一些集成测试,在该环境中,我需要隔离每个测试方案的事务,以便测试在操作数据库方面不会互相影响。
然后,在运行测试之后,我想检查数据库以查看工作是否正确完成。
到目前为止,我要做的是创建两个基础类,如下所示。 (我正在使用xunit作为测试框架)
document.documentElement
在这里,第一个(public class DatabaseInitializer : IDisposable
{
public readonly MyContext DatabaseContext;
public DatabaseInitializer()
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
var configuration = builder.Build();
DatabaseContext = new MyContext(configuration.GetConnectionString("SqlConnectionString"));
DatabaseContext.Database.EnsureCreated();
}
public void Dispose()
{
DatabaseContext.Database.EnsureDeleted();
}
}
public class TransactionIsolator : IClassFixture<DatabaseInitializer> , IDisposable
{
protected readonly TransactionScope TransactionScope;
protected readonly MyContext DatabaseContext;
public TransactionIsolator(DatabaseInitializer dbInitializer)
{
DatabaseContext = dbInitializer.DatabaseContext;
TransactionScope = new TransactionScope(TransactionScopeOption.RequiresNew);
}
public void Dispose()
{
TransactionScope.Dispose();
}
}
)将确保在测试套件的第一个运行时创建所需的数据库,然后在处置它时将其删除。
第二个类将创建一个事务,并在测试完成后回滚更改。因此,当我编写如下所示的两个测试时,它将正确隔离每个运行的测试用例对数据库的访问。
DatabaseInitializer
这些将被通过,并且一切都很好,除非我无权访问微服务来设置其事务,或者至少我不知道是否有可能。我的意思是,如果我可以配置或发信号通知微服务从该应用程序范围之外的数据库使用事务处理,那将非常棒。
此外,如果不可能的话,在这种情况下您可以建议使用什么?我想为每个测试方案获得隔离,并且仍然能够运行它们是并行的。
答案 0 :(得分:0)
对于大多数提供程序来说,这“有效”。 TransactionScope设置静态属性Transaction.Current,并且ADO.Net提供程序可以(通常这样做)征集环境事务。参见:Implementing an Implicit Transaction using Transaction Scope
至少对于SQL Server,如果您的测试使用相同的连接字符串,并且不能同时运行,则它们将也使用相同的SqlConnection,并且不需要升级为分布式事务。由于SQLClient连接池是按事务划分的,因此对池的相同请求(ConnectionString,Transaction)的后续请求将使用相同的SqlConnection。
还请注意,对于SQL Server,有些事务无法在事务内执行。您不能在事务中创建或更改数据库。但是您可以在事务中的数据库内部中创建表和索引。其他平台有不同的限制。例如,Oracle自动提交DDL语句。