首页 > 代码库 > c#单元测试:使用Moq框架Mock对象

c#单元测试:使用Moq框架Mock对象

在.net中有几种mock框架可供选择,比如NMock,PhinoMocks,FakeItEasy和Moq。尽管Moq相对较新,但是它非常易用。不需要像传统的Record/Replay。并且使用Moq在VS中可以得到智能提示。学习成本也不高。

这篇文章我们介绍下如何使用Moq来mock吧。

假定我们要做一个计算器提供基本的算术运算和不同货币的转换。

ICaculator接口定义如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace CalculatorPkg{    public interface ICalculator    {        int Add(int param1, int param2);        int Subtract(int param1, int param2);        int Multipy(int param1, int param2);        int Divide(int param1, int param2);        int ConvertUSDtoRMB(int unit);    }}

假定人民币转美元的接口定义如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace MoneyExchangeRatePkg{    public interface IUSD_RMB_ExchangeRateFeed    {        int GetActualUSDValue();    }}

下面是Calculator的实现类,其中人民币转美元的接口实例以构造函数参数的形式传给Calculator类。

using System;using System.Collections.Generic;using System.Linq;using System.Text;using MoneyExchangeRatePkg;namespace CalculatorPkg{    public class Calculator : ICalculator    {        private IUSD_RMB_ExchangeRateFeed _feed;        public Calculator(IUSD_RMB_ExchangeRateFeed feed)        {            this._feed = feed;        }        #region ICalculator Members        public int Add(int param1, int param2)        {            throw new NotImplementedException();        }         public int Subtract(int param1, int param2)        {            throw new NotImplementedException();        }        public int Multipy(int param1, int param2)        {            throw new NotImplementedException();        }        public int Divide(int param1, int param2)        {            return param1 / param2;        }        public int ConvertUSDtoRMB(int unit)        {            return unit * this._feed.GetActualUSDValue();        }        #endregion    }}

下面我们开始准备Calculator组件的测试环境,我们使用NUnit框架和Moq来做Mock。

您可以到http://www.nunit.org/获得nunit,到http://code.google.com/p/moq/获得moq框架的源码和dll文件。

然后我们就可以创建测试项目,并添加nunit和moq的引用。

我们要mock汇率的接口,下面是mock的方法:

Mock<IUSD_RMB_ExchangeRateFeed> mockObject = new Mock<IUSD_RMB_ExchangeRateFeed>();mockObject.Setup(m => m.GetActualUSDValue()).Returns(500);IUSD_RMB_ExchangeRateFeed value = mockObject.Object;

对汇率接口的MOCK只需要三行代码,第一行声明mock接口,第二行设定要mock方法的返回值,第三步通过Object属性获得mock的对象。

下面是完整的测试代码:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using NUnit.Framework;using Moq;using CalculatorPkg;using MoneyExchangeRatePkg;namespace CalculatorPkg.Tests{    // 添加TestFixture标识类是测试类    [TestFixture]    public class CalculatorTester    {        // 定义mock的逻辑        private IUSD_RMB_ExchangeRateFeed prvGetMockExchangeRateFeed()        {            Mock<IUSD_RMB_ExchangeRateFeed> mockObject = new Mock<IUSD_RMB_ExchangeRateFeed>();            mockObject.Setup(m => m.GetActualUSDValue()).Returns(500);            return mockObject.Object;        }        // 测试divide方法        [Test(Description="Divide 9 by 3. Expected result is 3.")]        public void TC1_Divide9By3()        {            IUSD_RMB_ExchangeRateFeed feed = this.prvGetMockExchangeRateFeed();            ICalculator calculator = new Calculator(feed);            int actualResult = calculator.Divide(9,3);            int expectedResult = 3;            Assert.AreEqual(expectedResult, actualResult);        }        [Test(Description = "Divide any number by zero. Should throw an System.DivideByZeroException exception.")]        [ExpectedException(typeof(System.DivideByZeroException))]        public void TC2_DivideByZero()        {            IUSD_RMB_ExchangeRateFeed feed = this.prvGetMockExchangeRateFeed();            ICalculator calculator = new Calculator(feed);            int actualResult = calculator.Divide(9, 0);        }        [Test(Description = "Convert 1 USD to RMB. Expected result is 500.")]        public void TC3_ConvertUSDtoRMBTest()        {            IUSD_RMB_ExchangeRateFeed feed = this.prvGetMockExchangeRateFeed();            ICalculator calculator = new Calculator(feed);            int actualResult = calculator.ConvertUSDtoRMB(1);            int expectedResult = 500;            Assert.AreEqual(expectedResult, actualResult);        }    }}
 
from:http://www.c-sharpcorner.com/uploadfile/john_charles/mocking-in-net-with-moq/

c#单元测试:使用Moq框架Mock对象