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);
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM