我有一个Web应用程序,它向DAL中的3个数据库发出请求。我正在编写一些集成测试,以确保整体功能往返实际上做我期望它做的事情。这与我的单元测试完全分开,只是提供信息。
我打算编写这些测试的方式是这样的:
在这种情况下,Presenter已经被设置好了。问题出现在ProcessWorkflow方法中,因为它调用各种仓库,而这些仓库又访问不同的数据库。我的SQL服务器框没有启用MSDTC,所以每当我尝试创建新的SQL连接或尝试更改缓存连接的数据库以针对不同的数据库时,就会出现错误。
为了简洁起见,Presenter类似于:
而 DataContext 本身大致如下所示。
我打算编写这些测试的方式是这样的:
[Test]
public void WorkflowExampleTest()
{
(using var transaction = new TransactionScope())
{
Presenter.ProcessWorkflow();
}
}
在这种情况下,Presenter已经被设置好了。问题出现在ProcessWorkflow方法中,因为它调用各种仓库,而这些仓库又访问不同的数据库。我的SQL服务器框没有启用MSDTC,所以每当我尝试创建新的SQL连接或尝试更改缓存连接的数据库以针对不同的数据库时,就会出现错误。
为了简洁起见,Presenter类似于:
public void ProcessWorkflow()
{
LogRepository.LogSomethingInLogDatabase();
var l_results = ProcessRepository.DoSomeWorkOnProcessDatabase();
ResultsRepository.IssueResultstoResultsDatabase(l_results);
}
我尝试了很多方法来解决这个问题。
- 始终缓存一个活动连接并更改目标数据库
- 为每个目标数据库缓存一个活动连接(这有点无用,因为池化应该替我完成此操作,但我想看看是否会得到不同的结果)
- 在每个存储库内添加其他TransactionScopes,以便它们拥有自己的事务,使用TransactionScopeOption“RequiresNew”
我列表中的第三种尝试看起来像这样:
public void LogSomethingInLogDatabase()
{
using (var transaction =
new TransactionScope(TransactionScopeOption.RequiresNew))
{
//do some database work
transaction.Complete();
}
}
实际上,我尝试的第三件事确实让单元测试正常工作了,但是所有完成的交易实际上都影响了我的数据库!因此这是一个彻底的失败,因为整个重点在于不影响我的数据库。
因此,我的问题是,在我提出的限制条件下,还有什么其他选项可以实现我想要做的事情?
编辑:
"//执行一些数据库操作"看起来就像这样
using (var l_context = new DataContext(TargetDatabaseEnum.SomeDatabase))
{
//use a SqlCommand here
//use a SqlDataAdapter inside the SqlCommand
//etc.
}
而 DataContext 本身大致如下所示。
public class DataContext : IDisposable
{
static int References { get; set; }
static SqlConnection Connection { get; set; }
TargetDatabaseEnum OriginalDatabase { get; set; }
public DataContext(TargetDatabaseEnum database)
{
if (Connection == null)
Connection = new SqlConnection();
if (Connection.Database != DatabaseInfo.GetDatabaseName(database))
{
OriginalDatabase =
DatabaseInfo.GetDatabaseEnum(Connection.Database);
Connection.ChangeDatabase(
DatabaseInfo.GetDatabaseName(database));
}
if (Connection.State == ConnectionState.Closed)
{
Connection.Open() //<- ERROR HAPPENS HERE
}
ConnectionReferences++;
}
public void Dispose()
{
if (Connection.State == ConnectionState.Open)
{
Connection.ChangeDatabase(
DatabaseInfo.GetDatabaseName(OriginalDatabase));
}
if (Connection != null && --ConnectionReferences <= 0)
{
if (Connection.State == ConnectionState.Open)
Connection.Close();
Connection.Dispose();
}
}
}