首页 > 代码库 > 初学 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可以是接口,也可以是类。它有一个Public和Virtual属性。比如:
定义一个接口界面:
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种重载,所以这里的Callbacks有5种重载。
(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