首页 > 代码库 > 初学 Moq

初学 Moq

 

1.什么是Moq?

 Moq是一个针对.Net开发的模拟库,它从开始就充分利用了(Linq表达式)和(Lambda表达式)。它的目标是让模拟以一种自然的方式与现有单元测试进行集成,使它更加简单、直观。使它成为了一个高生产力、类型安全、重构友好的模拟库。

2.从哪得到Moq?

可以直接使用VS中的插件Nuget来获取Moq并且引用到指定的项目。

 技术分享

 

3.Moq原理:

Moq使用Castle DynamicProxy完成这个任务。基本原理就是它利用反射机制的Emit功能动态生成一个空类型(也就是所有接口的方法都实例化,但是没有任何功能,只是一个程序骨架)。所以Mock的能力就在于可以利用DynamicProxy的机制快速生产出一个假对象来,用于模仿真对象的行为。

4.Moq中的重要成员

(1).Mock:通过这个类,我们可以得到一个Mock<T>对象。T可以是接口,也可以是类。它有一个PublicVirtual属性。比如:

定义一个接口界面:

public interface ITest
        {

            bool DoSomething(string actionname);

        }

定义测试方法:

 [TestMethod]
        public void Test_Interface_ITest()
        {
            //创建Mock对象,伪造一个ITest的实现
            var mo = new Mock<ITest>();
            //设置模拟对象
            mo.Setup(foo => foo.DoSomething("Ping")).Returns(true);(注意:Setup方法的参数是一个lambda表达式:可以这样理解:当被模拟的对象foo调用它自己的方法Dosomething(),并且参数是Pring。添加后缀名Return(true)可以这样理解:前边的请求返回结果为真。这是指定的返回值。当一个请求调用DoSomething()方法时。如果传入的参数是Pring,那么就返回true。然后添加一个断言,去判断是否能得到预期结果)

            //断言它
            Assert.AreEqual(true, mo.Object.DoSomething("Ping"));

      }

(2).It:这是一个静态类,定义了静态的泛型方法:

Is<TValue>IsAny<TValue>IslnRange<TValue>IsRegex。去过滤参数。

(3)MockBehavior:这个类用于模拟对象的行为。就像是否按照默认的模式去模拟

(4)Verification:有时候,我们要确定一个方法是否被调用了,或者甚至要知道它被调用了多少次。就使用Verify()方法。;例如:

mock.Verify(foo=>foo.DoSomething(Pring),Times.Once())

上边的代码尝试验证DoSomething(Pring)需要被调用,并且只调用一次。出了Once选项,也有更多的选项可以选择:如:Atleast(至少)AtLeastonce(至少一次),AtMost(最多),AtMostOnce(最多一次),Between(之间),Equals(等于),Exactly(确切的),Never(从未)Once(一次)

5.功能点介绍

(1).带有引用或输出参数的方法。例如:

{方法:string GetAddress(string strUser, out string Address);

string GetFamilyCall(ref string strUser);}定义两个方法
var customer = new Mock<ITest>();创建Mock对象,伪造一个ITest的实现

var outString="oo";

customer.Setup(p => p.GetAddress("", out outString)).Returns("sichuan");

customer.Setup(p => p.GetFamilyCall(ref outString)).Returns("xx");

(2)调用方法时抛出异常

方法:void ShowException(string str);

测试:var customer = new Mock<ITest>();

customer.Setup(p => p.ShowException(string.Empty))

.Throws(new Exception("参数不能为空!"));

customer.Object.ShowException("");

(3)Is<T>:匹配确定的给定类型

customer.Setup(x => x.SelfMatch(It.Is<int>(i => i % 2 == 0))).Returns("1");

方法SelfMatch接收int型的参数,当参数为偶数时,才返回字符串1.

(4)IsAny<T>:匹配给定的任何值

customer.Setup(p => p.SelfMatch(It.IsAny<int>())).Returns((int k) => "任何数:" + k);

方法SelfMatch接收int型,且任何int型参数都可以,然后返回:任何数:”+K.

(5)IsInRange<T>:匹配给定类型的范围

customer.Setup(p => p.SelfMatch(It.IsInRange<int>(0, 10, Range.Inclusive))).Returns("10以内的数");

方法SelfMatch接受int型,且当范围在[0,10]时,才返回10以内的数

其中,这个方法,带有一个包含与排除开关。

(6)IsRegex<T>:正则匹配

customer.Setup(p => p.ShowException(It.IsRegex(@"^\d+$")))

.Throws(new Exception("不能是数字"));

(7)Callbacks回调函数

当执行某方法时,调用其内部输入的(Action)委托,有它的5种重载:

Callback(Action)

Callback<T>(Action<T>)

Callback<T1, T2>(Action<T1, T2>)

Callback<T1, T2, T3>(Action<T1, T2, T3>)

Callback<T1, T2, T3, T4>(Action<T1, T2, T3, T4>)

这个方法调用其内部输入的Action委托,Aciton<T>5种重载,所以这里的Callbacks5种重载。

(8).Verify验证

用于测试mock对象的方法或属性是否被调用执行.也有很多重载:

Verify()

Verify(Expression<Action<T>>)

Verify<TResult>(Expression<Func<T, TResult>>)

Verify(Expression<Action<T>>, Times)

Verify(Expression<Action<T>>, String)

Verify<TResult>(Expression<Func<T, TResult>>, Times)

Verify<TResult>(Expression<Func<T, TResult>>, String)

Verify(Expression<Action<T>>, Times, String)

Verify<TResult>(Expression<Func<T, TResult>>, Times, String)

(9).VerifyAll验证

在使用Verify方法时,只有被标记为可证实的(.Verifiable())的才可以验证。

 

 

 

 

 

 

 

初学 Moq