• 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);
            }
        }
    }
     
  • 相关阅读:
    JSON 之 SuperObject(10): Merge、Clone、ForcePath
    JSON 之 SuperObject(5): Format 与转义字符
    语法基础: 使用不同的数据类型标记数组
    JSON 之 SuperObject(9): TSuperType
    JSON 之 SuperObject(12): TSuperEnumerator、TSuperAvlIterator、ObjectFindFirst...
    JSON 之 SuperObject(7): 可以省略的双引号
    JSON 之 SuperObject(11): TSuperTableString、TSuperAvlEntry
    JSON 之 SuperObject(13): 关于 SO 与 SA 函数
    JSON 之 SuperObject(8): 关于乱码的几种情况 向 Henri Gourvest 大师报告
    安装万能五笔时会自动安装copyso
  • 原文地址:https://www.cnblogs.com/zjoch/p/6565757.html
Copyright © 2020-2023  润新知