挽星

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

我们在做单元测试的时候,常常困扰于数据的持久化疑问 ,很多情况下我们不希望单元测试影响到数据库中的内容,而且受数据库的影响有时我们的单元测试的速度会很慢,所以我们往往希望将持久化部分隔离开,做单元测试的时候不真实 的将数据持久化。这种隔离我们一般运用 抽象的方式,也就是运用 接口或抽象类将持久化层隔离开,然后运用 mock来模拟相应的接口或抽象类来完成相应的持久化类。MoQ就是这种Mock框架之一,MoQ运用 了C#3.0,跟 NMock相比MoQ运用 起来更基本 ,而且是强类型的方式的,源码和dll可以到http://code.Google.com/p/moq/下载。现在MoQ最新的揭晓 版本是3.1版,4.0还处在beta版中,所以我们这里运用 的是3.1版。
  下面我们就来介绍一下MoQ的具体用法:
  一、基础知识
  在运用 MoQ之前我们必须要先在测试程序中引入Moq.dll,运用 MoQ的主要命名空间是Moq,其中最重的类就是Mock<T>,我们可以用这个类来模拟接口。
  1、要领
      public interface ITest
    {
        string Test();
    }
  测试代码:
  基本 测试代码
      [TestMethod()]
      public void TestTest()
      {
         var test = new Mock<ITest>();
         test.Setup(p => p.Test()).Returns("lfm");
         Assert.AreEqual("lfm", test.Object.Test());
      }
  2、匹配参数
         public interface IMatchTest
    {
        string Test(int test);
    }

  匹配测试
var testMatch = new Mock<IMatchTest>();
            testMatch.Setup(p => p.Test(It.Is<int>(i => i % 2 == 0))).Returns("偶数");
            testMatch.Setup(p => p.Test(It.Is<int>(i => i % 2 != 0))).Returns("奇数");
            Assert.AreEqual("偶数", testMatch.Object.Test(4));
            Assert.AreEqual("奇数", testMatch.Object.Test(3));
  上边测试代码模拟实现IMathTest接口实例,其中如果Test要领 的参数是偶数,其返回值为“偶数”。这里的IT用来过滤参数的类,其具体解释可以参见MoQ的文档
  3、属性
         public interface IPropertiesTest
    {
         int Test { get; set; }
    }
 
            var testProperties = new Mock<IPropertiesTest>();
            testProperties.Setup(p => p.Test).Returns(1);
            Assert.AreEqual(1, testProperties.Object.Test);
或者
                                 var testProperties = new Mock<IPropertiesTest>();
            testProperties.SetupProperty(p => p.Test,1);
            Assert.AreEqual(1, testProperties.Object.Test);
  4、Callback
  当执行某要领 时调用其内部输入的Action委托

int count = 0;
            var testProperties = new Mock<IPropertiesTest>();
            testProperties.Setup(p => p.Test).Returns(1).Callback(()=>count++);
            Assert.AreEqual(1, testProperties.Object.Test);
            Assert.AreEqual(1, count);
  在调用Test要领 是执行了count++
  5、Verification
  判断某要领 或属性能不能 执行过
  如果代码如下:
                                   var testProperties = new Mock<IPropertiesTest>();
             testProperties.Setup(p => p.Test).Returns(1);
             testProperties.Verify(p => p.Test);
             Assert.AreEqual(1, testProperties.Object.Test);
  会抛出异常,因为第3行执行时Test要领 还没有被调用过,改为如下代码可以通过测试
                         var testProperties = new Mock<IPropertiesTest>();
            testProperties.Setup(p => p.Test).Returns(1);
            Assert.AreEqual(1, testProperties.Object.Test);
            testProperties.Verify(p => p.Test);
  其他细节可以查看MoQ文档。
  二、运用
  先建立 一个Account类:

      

     建立 一个数据库Provider接口:
   public interface ITransferProvider
    {
        void TransferTo(Account accountFrom, Account accountTo);
    }
  然后建立 转账处理类:
             TransferProcess
             public class TransferProcess
      {
          private Account From;
          private Account To;
          private ITransferProvider transfer;
          public TransferProcess(Account from, Account to, ITransferProvider transfer)
          {
              this.From = from;
              this.To = to;
             this.transfer = transfer;
         }
         public void Transfer(decimal money)
         {
             if (money<From.Money)
             {
                 From.Money = From.Money - money;
                 To.Money = To.Money + money;
                 transfer.TransferTo(From, To);
             }
             else
             {
                 throw new Exception("超出余额");
             }
         }
     }

      下边我们来测试这个转账处理类:
   var transfer = new Mock<ITransferProvider>();
            Account accountFrom = new Account() { AccountNum = 1, Money = 1000, Name = "lfm1" };
            Account accountTo = new Account() { AccountNum = 2, Money = 1000, Name = "lfm1" };
            TransferProcess tp = new TransferProcess(accountFrom, accountTo, transfer.Object);
            tp.Transfer(500);
            Assert.AreEqual(500, accountFrom.Money);
            Assert.AreEqual(1500, accountTo.Money);

posted on 2011-01-17 11:21  挽星  阅读(2173)  评论(0)    收藏  举报