using System; using System.Reflection; using System.Transactions; using Xunit.Sdk; namespace Bootstrap.DataAccess { /// /// Apply this attribute to your test method to automatically create a /// that is rolled back when the test is finished. /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public sealed class AutoRollbackAttribute : BeforeAfterTestAttribute { private TransactionScope scope; /// /// Gets or sets whether transaction flow across thread continuations is enabled for TransactionScope. /// By default transaction flow across thread continuations is enabled. /// public TransactionScopeAsyncFlowOption AsyncFlowOption { get; set; } = TransactionScopeAsyncFlowOption.Enabled; /// /// Gets or sets the isolation level of the transaction. /// Default value is .Unspecified. /// public IsolationLevel IsolationLevel { get; set; } = IsolationLevel.Unspecified; /// /// Gets or sets the scope option for the transaction. /// Default value is .Required. /// public TransactionScopeOption ScopeOption { get; set; } = TransactionScopeOption.Required; /// /// Gets or sets the timeout of the transaction, in milliseconds. /// By default, the transaction will not timeout. /// public long TimeoutInMS { get; set; } = -1; /// /// Rolls back the transaction. /// public override void After(MethodInfo methodUnderTest) { scope.Dispose(); } /// /// Creates the transaction. /// public override void Before(MethodInfo methodUnderTest) { var options = new TransactionOptions { IsolationLevel = IsolationLevel }; if (TimeoutInMS > 0) options.Timeout = TimeSpan.FromMilliseconds(TimeoutInMS); scope = new TransactionScope(ScopeOption, options, AsyncFlowOption); } } }