在.net中有幾種mock框架可供選擇,好比NMock,PhinoMocks,FakeItEasy和Moq。儘管Moq相對較新,可是它很是易用。不須要像傳統的Record/Replay。而且使用Moq在VS中能夠獲得智能提示。學習成本也不高。框架
這篇文章咱們介紹下如何使用Moq來mock吧。ide
假定咱們要作一個計算器提供基本的算術運算和不一樣貨幣的轉換。函數
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類。this
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。google
您能夠到http://www.nunit.org/得到nunit,到http://code.google.com/p/moq/得到moq框架的源碼和dll文件。spa
而後咱們就能夠建立測試項目,並添加nunit和moq的引用。.net
咱們要mock匯率的接口,下面是mock的方法:code
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); } } }