使用事务自动回滚来实现单元测试
作者:网络转载 发布时间:[ 2013/6/17 10:31:56 ] 推荐标签:
我们没有使用TDD,所以单元测试麻烦的是准备测试的基础数据。我们现在是使用内存仓储来做单元测试,要为每个仓储都构造基础数据,非常麻烦。
前几天看xunit的源码,看到AutoRollbackAttribute这个特性,异常的兴奋 ^_^。怎么忘了用事务的自动回滚呢?
我们看AutorollbackAttribute的具体实现:
public class AutoRollbackAttribute : BeforeAfterTestAttribute
{
IsolationLevel isolationLevel = IsolationLevel.Unspecified;
TransactionScope scope;
TransactionScopeOption scopeOption = TransactionScopeOption.Required;
long timeoutInMS = -1;
/// <summary>
/// Gets or sets the isolation level of the transaction.
/// Default value is <see cref="IsolationLevel"/>.Unspecified.
/// </summary>
public IsolationLevel IsolationLevel
{
get { return isolationLevel; }
set { isolationLevel = value; }
}
/// <summary>
/// Gets or sets the scope option for the transaction.
/// Default value is <see cref="TransactionScopeOption"/>.Required.
/// </summary>
public TransactionScopeOption ScopeOption
{
get { return scopeOption; }
set { scopeOption = value; }
}
/// <summary>
/// Gets or sets the timeout of the transaction, in milliseconds.
/// By default, the transaction will not timeout.
/// </summary>
public long TimeoutInMS
{
get { return timeoutInMS; }
set { timeoutInMS = value; }
}
/// <summary>
/// Rolls back the transaction.
/// </summary>
public override void After(MethodInfo methodUnderTest)
{
scope.Dispose();
}
/// <summary>
/// Creates the transaction.
/// </summary>
public override void Before(MethodInfo methodUnderTest)
{
TransactionOptions options = new TransactionOptions();
options.IsolationLevel = isolationLevel;
if (timeoutInMS > 0)
options.Timeout = new TimeSpan(timeoutInMS * 10);
scope = new TransactionScope(scopeOption, options);
}
}
这里使用了.Net Framework自带的TransactionScope。TransactionScope在.NET 2.0中已经有了,可用于分布式事务。用这种方法来做数据的自动回滚也有一些不足:
1、数据库要支持事务。
2、内部数据库操作的逻辑里没有事务的实现。
很庆幸的是我们的项目正好都满足上面的2点,不足的是mongodb不支持事务。所以需要混合仓储实现了,事务数据库使用真实的仓储,mongodb使用内存仓储。

sales@spasvo.com