Unit Testing the Use of TransactionScope

后端 未结 5 1235
情书的邮戳
情书的邮戳 2021-01-31 09:35

The preamble: I have designed a strongly interfaced and fully mockable data layer class that expects the business layer to create a TransactionScope when multip

5条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-01-31 10:04

    I found a great way to test this using Moq and FluentAssertions. Suppose your unit under test looks like this:

    public class Foo
    {
        private readonly IDataLayer dataLayer;
    
        public Foo(IDataLayer dataLayer)
        {
            this.dataLayer = dataLayer;
        }
    
        public void MethodToTest()
        {
            using (var transaction = new TransactionScope())
            {
                this.dataLayer.Foo();
                this.dataLayer.Bar();
                transaction.Complete();
            }
        }
    }
    

    Your test would look like this (assuming MS Test):

    [TestClass]
    public class WhenMethodToTestIsCalled()
    {
        [TestMethod]
        public void ThenEverythingIsExecutedInATransaction()
        {
            var transactionCommitted = false;
            var fooTransaction = (Transaction)null;
            var barTransaction = (Transaction)null;
    
            var dataLayerMock = new Mock();
    
            dataLayerMock.Setup(dataLayer => dataLayer.Foo())
                         .Callback(() =>
                                   {
                                       fooTransaction = Transaction.Current;
                                       fooTransaction.TransactionCompleted +=
                                           (sender, args) =>
                                           transactionCommitted = args.Transaction.TransactionInformation.Status == TransactionStatus.Committed;
                                   });
    
            dataLayerMock.Setup(dataLayer => dataLayer.Bar())
                         .Callback(() => barTransaction = Transaction.Current);
    
            var unitUnderTest = new Foo(dataLayerMock.Object);
    
            unitUnderTest.MethodToTest();
    
            // A transaction was used for Foo()
            fooTransaction.Should().NotBeNull();
    
            // The same transaction was used for Bar()
            barTransaction.Should().BeSameAs(fooTransaction);
    
            // The transaction was committed
            transactionCommitted.Should().BeTrue();
        }
    }
    

    This works great for my purposes.

提交回复
热议问题