前几天调查完了unity。现在给我的任务是让我调查Moq。
  以下是自己找了资料,总结并实践的内容。如果有表述和理解错误的地方。恳请指正。
  什么是Moq?
  Moq(英语发音是Mock-you 或者只是mock)是一个针对.Net开发的模拟库,它从开始完全充分利用了.NET3.5(LINQ表达式树)和C#3.0的新特性(lambda表达式)。它的目标是让模拟以一种自然的方式与现有单元测试进行集成,使它更加简单、直观,以避免开发人员被迫重写测试或高成本的学习测试框架。这使它成为了一个高生产力、类型安全、重构友好的模拟库。
  从哪得到Moq?
  如果你看过我的其他文章,我们可以直接使用 VS中的插件Nuget来获取Moq并且引用到指定的项目。

  否则,我们可以从http://code.google.com/p/moq/这里得到Moq的新版本。
  可以模拟什么?局限性
  首先,模拟的类不能是密封的。
  其次,你不能直接模拟静态方法。因为Moq只能创建模拟对象实例。在这种情况下,间接的解决方案是我们可以在要模拟对象外包装一层,并且去模拟这个新对象。这种模式被称为适配器模式。
  通常我们测试一个方法,它有可能调用好几个service。但是每次都去访问这些service的代价是很高的。我们可以通过模拟的方法让它模拟访问service,并且根据不同请求模拟返回响应的结果。
  Moq原理
  Moq是如何办到的?它只需要一个接口类型可以生产一个对象?没错,是这样。Moq使用 Castle DynamicProxy 完成这个任务。基本原理是它利用反射机制的 Emit 功能动态生成一个空类型(也是所有接口的方法都实例化,但是没有任何功能,只是一个程序骨架)。所以Mock的能力在于可以利用DynamicProxy的机制快速生产出一个假对象来,用于模仿真对象的行为。
  Moq中的重要成员
  Mock
  通过这个类,我们可以得到一个Mock<T>对象。T可以是接口,也可以是类。它有一个public 和virtual属性。让我们看看下边的例子:

//define interface to be mocked
public interface IFake
{
bool DoSomething(string actionname);
}
//define the test method
public void Test_Interface_IFake()
{
//make a mock Object by Moq
var mo = new Mock<IFake>();
//Setup our mock object
mo.Setup(foo => foo.DoSomething("Ping"))
.Returns(true);
//Assert it!
Assert.AreEqual(true, mo.Object.DoSomething("Ping"));
}
  在上边的代码,我们通过传递泛型参数IFake去创建Mock<IFake>的实例 模拟接口IFake。
  接下来我们要调用Setup()方法去创建我们的模拟对象。注意,Setup方法的参数是一个lambda表达式。我们可以这样理解:当被模拟的对象foo调用它自己的方法DoSomething(),并且参数是Ping。添加后缀 Return (true)我们可以理解为:前边的请求返回结果为真。这是我们指定的返回值。当一个请求调用DoSomething()方法时。如果传入的参数是 Ping,那么我们会返回true。接下来,我们添加一个断言,去判断是否能得到预期结果。
  注:Foo仅仅是一个词用作通用替代真实的东西,特别是在讨论技术想法和问题.
  It
  这是一个静态类,定义了静态的泛型方法:Is<TValue>, IsAny<TValue>, IsInRange<TValue>, 和IsRegex。去过滤参数。看看下边例子:
public interface IEmailSender
{
bool Send(string subject, string body, string email);
}
public void User_Can_Send_Password()
{
var emailMock = new Mock<IEmailSender>();
emailMock
.Setup(sender => sender.Send(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(true);
}
  任何时候调用Send()方法,只要传入的参数是任何的string,我们定义他会返回true。
  我们也可以根据lambda的优势订制一个规则:
  var productRepository = new Mock<IProductRepository>();
  productRepository
  .Expect(p => p.Get(It.Is<int>(id => id > 0 && id < 6)))
  .Returns(newProduct.Object);
  这样我们可以设置这个id在0和6之间的时候才会返回一个新的对象。上边提及到的其他方法,我们可以参考这里的教程 Moq’s QuickStart
  此外,这个类的增强版是 Match<T>,你完全可以自定义模拟规则。
  MockBehavior
上一页12下一页
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。