Moq


1 My Cases

1.1 简单入门

2 Reference

2.1 Methods

2.2 Matching Arguments

2.3 Properties

2.4 Events

2.5 Callbacks

2.6 Verification

2.7 Customizing Mock Behavior

2.8 Miscellaneous

2.9 Advanced Features

2.10 LINQ to Mocks

3 FAQ

3.1 static class/method


1 My Cases

1.1 简单入门

// 假定我有一个 MyFactory 用来创建 MyInterface 实例
// 创建 MyFactory 的 Mock 对象
var mockFactory = new Mock<MyFactory>(); // 创建 MyInterface 的 Mock 实例
var mockInstance = new Mock<MyInterface>(); // 使用 Moq 实现如果调用 MyInstance.DoSomething(bool) 方法无论传入参数为何值一概抛出 MyException 异常
mockInstance.Setup(c => c.DoSomething(It.IsAny<bool>()))
.Throws(new MyException("my exception message")); // 使用 Moq 实现 MyFactory 的 Mock 实例第一次调用 CreateInstance(string) 方法时返回 MyInterface 的 Mock 实例
// 第二次及以后调用则返回真正的 MyInstance 实例
mockFactory.SetupSequence(f => f.CreateInstance(It.IsAny<string>()))
.Returns(mockInstance.Object)
.Returns(new MyInstance("real object")); client.Factory = mockFactory.Object;

2 Reference

Please refer to Moq Quickstart

Moq is intended to be simple to use, strongly typed (no magic strings!, and therefore full compiler-verified and refactoring-friendly) and minimalistic (while still fully functional!).

2.1 Methods

Methods Mock

using Moq;

// Assumptions:

public interface IFoo
{
Bar Bar { get; set; }
string Name { get; set; }
int Value { get; set; }
bool DoSomething(string value);
bool DoSomething(int number, string value);
string DoSomethingStringy(string value);
bool TryParse(string value, out string outputValue);
bool Submit(ref Bar bar);
int GetCount();
bool Add(int value);
} public class Bar
{
public virtual Baz Baz { get; set; }
public virtual bool Submit() { return false; }
} public class Baz
{
public virtual string Name { get; set; }
} var mock = new Mock<IFoo>();
mock.Setup(foo => foo.DoSomething("ping")).Returns(true); // out arguments
var outString = "ack";
// TryParse will return true, and the out argument will return "ack", lazy evaluated
mock.Setup(foo => foo.TryParse("ping", out outString)).Returns(true); // ref arguments
var instance = new Bar();
// Only matches if the ref argument to the invocation is the same instance
mock.Setup(foo => foo.Submit(ref instance)).Returns(true); // access invocation arguments when returning a value
mock.Setup(x => x.DoSomethingStringy(It.IsAny<string>()))
.Returns((string s) => s.ToLower());
// Multiple parameters overloads available // throwing when invoked with specific parameters
mock.Setup(foo => foo.DoSomething("reset")).Throws<InvalidOperationException>();
mock.Setup(foo => foo.DoSomething("")).Throws(new ArgumentException("command")); // lazy evaluating return value
var count = 1;
mock.Setup(foo => foo.GetCount()).Returns(() => count); // returning different values on each invocation
var mock = new Mock<IFoo>();
var calls = 0;
mock.Setup(foo => foo.GetCount())
.Returns(() => calls)
.Callback(() => calls++);
// returns 0 on first invocation, 1 on the next, and so on
Console.WriteLine(mock.Object.GetCount());

2.2 Matching Arguments

Arguments Mock

// any value
mock.Setup(foo => foo.DoSomething(It.IsAny<string>())).Returns(true); // any value passed in a `ref` parameter (requires Moq 4.8 or later):
mock.Setup(foo => foo.Submit(ref It.Ref<Bar>.IsAny)).Returns(true); // matching Func<int>, lazy evaluated
mock.Setup(foo => foo.Add(It.Is<int>(i => i % 2 == 0))).Returns(true); // matching ranges
mock.Setup(foo => foo.Add(It.IsInRange<int>(0, 10, Range.Inclusive))).Returns(true); // matching regex
mock.Setup(x => x.DoSomethingStringy(It.IsRegex("[a-d]+", RegexOptions.IgnoreCase))).Returns("foo");

2.3 Properties

  • Common

    Arguments Mock

    mock.Setup(foo => foo.Name).Returns("bar");
    
    // auto-mocking hierarchies (a.k.a. recursive mocks)
    mock.Setup(foo => foo.Bar.Baz.Name).Returns("baz"); // expects an invocation to set the value to "foo"
    mock.SetupSet(foo => foo.Name = "foo"); // or verify the setter directly
    mock.VerifySet(foo => foo.Name = "foo");
  • Setup a property so that it will automatically start tracking its value (also known as Stub)

    Arguments Mock

    // start "tracking" sets/gets to this property
    mock.SetupProperty(f => f.Name); // alternatively, provide a default value for the stubbed property
    mock.SetupProperty(f => f.Name, "foo"); // Now you can do: IFoo foo = mock.Object;
    // Initial value was stored
    Assert.Equal("foo", foo.Name); // New value set which changes the initial value
    foo.Name = "bar";
    Assert.Equal("bar", foo.Name);
  • Stub all properties on a mock (not available on Silverlight)

    mock.SetupAllProperties();
    

2.4 Events

Events Mock

// Raising an event on the mock
mock.Raise(m => m.FooEvent += null, new FooEventArgs(fooValue)); // Raising an event on the mock that has sender in handler parameters
mock.Raise(m => m.FooEvent += null, this, new FooEventArgs(fooValue)); // Raising an event on a descendant down the hierarchy
mock.Raise(m => m.Child.First.FooEvent += null, new FooEventArgs(fooValue)); // Causing an event to raise automatically when Submit is invoked
mock.Setup(foo => foo.Submit()).Raises(f => f.Sent += null, EventArgs.Empty);
// The raised event would trigger behavior on the object under test, which
// you would make assertions about later (how its state changed as a consequence, typically) // Raising a custom event which does not adhere to the EventHandler pattern
public delegate void MyEventHandler(int i, bool b);
public interface IFoo
{
event MyEventHandler MyEvent;
} var mock = new Mock<IFoo>();
...
// Raise passing the custom arguments expected by the event delegate
mock.Raise(foo => foo.MyEvent += null, 25, true);

2.5 Callbacks

Mock Callback

var mock = new Mock<IFoo>();
var calls = 0;
var callArgs = new List<string>(); mock.Setup(foo => foo.DoSomething("ping"))
.Returns(true)
.Callback(() => calls++); // access invocation arguments
mock.Setup(foo => foo.DoSomething(It.IsAny<string>()))
.Returns(true)
.Callback((string s) => callArgs.Add(s)); // alternate equivalent generic method syntax
mock.Setup(foo => foo.DoSomething(It.IsAny<string>()))
.Returns(true)
.Callback<string>(s => callArgs.Add(s)); // access arguments for methods with multiple parameters
mock.Setup(foo => foo.DoSomething(It.IsAny<int>(), It.IsAny<string>()))
.Returns(true)
.Callback<int, string>((i, s) => callArgs.Add(s)); // callbacks can be specified before and after invocation
mock.Setup(foo => foo.DoSomething("ping"))
.Callback(() => Console.WriteLine("Before returns"))
.Returns(true)
.Callback(() => Console.WriteLine("After returns")); // callbacks for methods with `ref` / `out` parameters are possible but require some work (and Moq 4.8 or later):
delegate void SubmitCallback(ref Bar bar); mock.Setup(foo => foo.Submit(ref It.Ref<Bar>.IsAny)
.Callback(new SubmitCallback((ref Bar bar) => Console.WriteLine("Submitting a Bar!"));

2.6 Verification

Mock Verification

mock.Verify(foo => foo.DoSomething("ping"));

// Verify with custom error message for failure
mock.Verify(foo => foo.DoSomething("ping"), "When doing operation X, the service should be pinged always"); // Method should never be called
mock.Verify(foo => foo.DoSomething("ping"), Times.Never()); // Called at least once
mock.Verify(foo => foo.DoSomething("ping"), Times.AtLeastOnce()); // Verify getter invocation, regardless of value.
mock.VerifyGet(foo => foo.Name); // Verify setter invocation, regardless of value.
mock.VerifySet(foo => foo.Name); // Verify setter called with specific value
mock.VerifySet(foo => foo.Name ="foo"); // Verify setter with an argument matcher
mock.VerifySet(foo => foo.Value = It.IsInRange(1, 5, Range.Inclusive)); // Verify that no other invocations were made other than those already verified (requires Moq 4.8 or later)
mock.VerifyNoOtherCalls();

2.7 Customizing Mock Behavior

  • Make mock behave like a "true Mock", raising exceptions for anything that doesn't have a corresponding expectation: in Moq slang a "Strict" mock; default behavior is "Loose" mock, which never throws and returns default values or empty arrays, enumerables, etc. if no expectation is set for a member

    var mock = new Mock<IFoo>(MockBehavior.Strict);
    
  • Invoke base class implementation if no expectation overrides the member (a.k.a. "Partial Mocks" in Rhino Mocks): default is false. (this is required if you are mocking Web/Html controls in System.Web!)

    var mock = new Mock<IFoo> { CallBase = true };
    
  • Make an automatic recursive mock: a mock that will return a new mock for every member that doesn't have an expectation and whose return value can be mocked (i.e. it is not a value type)

    var mock = new Mock<IFoo> { DefaultValue = DefaultValue.Mock };
    // default is DefaultValue.Empty // this property access would return a new mock of Bar as it's "mock-able"
    Bar value = mock.Object.Bar; // the returned mock is reused, so further accesses to the property return
    // the same mock instance. this allows us to also use this instance to
    // set further expectations on it if we want
    var barMock = Mock.Get(value);
    barMock.Setup(b => b.Submit()).Returns(true);
  • Centralizing mock instance creation and management: you can create and verify all mocks in a single place by using a MockRepository, which allows setting the MockBehavior, its CallBase and DefaultValue consistently

    var repository = new MockRepository(MockBehavior.Strict) { DefaultValue = DefaultValue.Mock };
    
    // Create a mock using the repository settings
    var fooMock = repository.Create<IFoo>(); // Create a mock overriding the repository settings
    var barMock = repository.Create<Bar>(MockBehavior.Loose); // Verify all verifiable expectations on all mocks created through the repository
    repository.Verify();

2.8 Miscellaneous

  • Setting up a member to return different values / throw exceptions on sequential calls:

    var mock = new Mock<IFoo>();
    mock.SetupSequence(f => f.GetCount())
    .Returns(3) // will be returned on 1st invocation
    .Returns(2) // will be returned on 2nd invocation
    .Returns(1) // will be returned on 3rd invocation
    .Returns(0) // will be returned on 4th invocation
    .Throws(new InvalidOperationException()); // will be thrown on 5th invocation
  • Setting expectations for protected members (you can't get IntelliSense for these, so you access them using the member name as a string):

    // at the top of the test fixture
    using Moq.Protected; // in the test
    var mock = new Mock<CommandBase>();
    mock.Protected()
    .Setup<int>("Execute")
    .Returns(5); // if you need argument matching, you MUST use ItExpr rather than It
    // planning on improving this for vNext (see below for an alternative in Moq 4.8)
    mock.Protected()
    .Setup<bool>("Execute",
    ItExpr.IsAny<string>())
    .Returns(true);
  • Moq 4.8 and later allows you to set up protected members through a completely unrelated type that has the same members and thus provides the type information necessary for IntelliSense to work. You can also use this interface to set up protected generic methods and those having by-ref parameters:

    interface CommandBaseProtectedMembers
    {
    bool Execute(string arg);
    } mock.Protected().As<CommandBaseProtectedMembers>()
    .Setup(m => m.Execute(It.IsAny<string>())) // will set up CommandBase.Execute
    .Returns(true);

2.9 Advanced Features

  • Common

    // get mock from a mocked instance
    IFoo foo = // get mock instance somehow
    var fooMock = Mock.Get(foo);
    fooMock.Setup(f => f.GetCount()).Returns(42); // implementing multiple interfaces in mock
    var mock = new Mock<IFoo>();
    var disposableFoo = mock.As<IDisposable>();
    // now the IFoo mock also implements IDisposable :)
    disposableFoo.Setup(disposable => disposable.Dispose()); // implementing multiple interfaces in single mock
    var mock = new Mock<IFoo>();
    mock.Setup(foo => foo.Name).Returns("Fred");
    mock.As<IDisposable>().Setup(disposable => disposable.Dispose()); // custom matchers
    mock.Setup(foo => foo.DoSomething(IsLarge())).Throws<ArgumentException>();
    ...
    public string IsLarge()
    {
    return Match.Create<string>(s => !String.IsNullOrEmpty(s) && s.Length > 100);
    }
  • Mocking internal types: Add either of the following custom attributes (typically in AssemblyInfo.cs) to the project containing the internal types — which one you need depends on whether your own project is strong-named or not:

    // This assembly is the default dynamic assembly generated by Castle DynamicProxy,
    // used by Moq. If your assembly is strong-named, paste the following in a single line:
    [assembly:InternalsVisibleTo("DynamicProxyGenAssembly2,PublicKey=00...cc7")] // Or, if your own assembly is not strong-named, omit the public key:
    [assembly:InternalsVisibleTo("DynamicProxyGenAssembly2")]
  • Starting in Moq 4.8, you can create your own custom default value generation strategies (besides DefaultValue.Empty and DefaultValue.Mock) by subclassing DefaultValueProvider, or, if you want some more convenience, LookupOrFallbackDefaultValueProvider:

    class MyEmptyDefaultValueProvider : LookupOrFallbackDefaultValueProvider
    {
    public MyEmptyDefaultValueProvider()
    {
    base.Register(typeof(string), (type, mock) => "?");
    base.Register(typeof(List<>), (type, mock) => Activator.CreateInstance(type));
    }
    } var mock = new Mock<IFoo> { DefaultValueProvider = new MyEmptyDefaultValueProvider() };
    var name = mock.Object.Name; // => "?"

    Note: When you pass the mock for consumption, you must pass mock.Object, not mock itself.

2.10 LINQ to Mocks

Moq is the one and only mocking framework that allows specifying mock behavior via declarative specification queries. You can think of LINQ to Mocks as:

Keep that query form in mind when reading the specifications:

var services = Mock.Of<IServiceProvider>(sp =>
sp.GetService(typeof(IRepository)) == Mock.Of<IRepository>(r => r.IsAuthenticated == true) &&
sp.GetService(typeof(IAuthentication)) == Mock.Of<IAuthentication>(a => a.AuthenticationType == "OAuth")); // Multiple setups on a single mock and its recursive mocks
ControllerContext context = Mock.Of<ControllerContext>(ctx =>
ctx.HttpContext.User.Identity.Name == "kzu" &&
ctx.HttpContext.Request.IsAuthenticated == true &&
ctx.HttpContext.Request.Url == new Uri("http://moqthis.com") &&
ctx.HttpContext.Response.ContentType == "application/xml"); // Setting up multiple chained mocks:
var context = Mock.Of<ControllerContext>(ctx =>
ctx.HttpContext.Request.Url == new Uri("http://moqthis.me") &&
ctx.HttpContext.Response.ContentType == "application/xml" &&
// Chained mock specification
ctx.HttpContext.GetSection("server") == Mock.Of<ServerSection>(config =>
config.Server.ServerUrl == new Uri("http://moqthis.com/api"));

LINQ to Mocks is great for quickly stubbing out dependencies that typically don't need further verification. If you do need to verify later some invocation on those mocks, you can easily retrieve them with Mock.Get(instance).

3 FAQ

3.1 static class/method

Moq 不支持对静态类或方法的 mock. 作为变通,可以使用实例方法来调用静态方法,再去 mock 实例方法。

C# Moq的更多相关文章

  1. Moq基础

    一.概念 Moq是利用诸如Linq表达式树和Lambda表达式等·NET 3.5的特性,为·NET设计和开发的Mocking库.Mock字面意思即模拟,模拟对象的行为已达到欺骗目标(待测试对象)的效果 ...

  2. 单元测试与Moq

    这个篇幅里面,记录单元测试与Moq模拟包的知识点. 单元测试 每一个模块,都应该有对应的单元测试.单元测试可以保证你的代码准确性,大大减少出现BUG的几率.一个好的单元测试,也是重构代码必不可少的部分 ...

  3. moq 的常用使用方法

    测试方法                             Console.WriteLine(mock.Object.GetCountThing()); 匹配参数   mock.Setup(x ...

  4. 单元测试中使用Moq对EF的DbSet进行mock

    刚用上Moq,就用它解决了一个IUnitOfWork的mock问题,在这篇博文中记录一下. 开发场景 Application服务层BlogCategoryService的实现代码如下: public ...

  5. 【MVC 4】4.MVC 基本工具(Visual Studio 的单元测试、使用Moq)

     作者:[美]Adam Freeman      来源:<精通ASP.NET MVC 4> 3.Visual Studio 的单元测试 有很多.NET单元测试包,其中很多是开源和免费的.本 ...

  6. 【Pro ASP.NET MVC 3 Framework】.学习笔记.4.MVC的主要工具-使用Moq

    在之前的例子中,我们创建了FakeRepository类来支持我们的测试.但是我们还没有解释如何穿件一个真实的repository实现,我们需要一个替代品.一旦我们有一个真的实现,我们可能不会再用它, ...

  7. Moq的使用

    参考资料: 1. http://www.codeproject.com/Tips/729646/TDD-using-MOQ 2. https://github.com/Moq/moq4/wiki/Qu ...

  8. 使用Ninject+Moq在单元测试中抽象数据访问层

    一.测试方法的业务逻辑时,通常都需要从数据库读取测试数据,但是每次初始化数据库数据都很麻烦,也会影响到其它业务对数据的访问,怎样抽象数据访问层呢?就是用Moq去模拟数据访问的逻辑     二.步骤如下 ...

  9. 【PRO ASP.NE MVC4 学习札记】使用Moq辅助进行单元测试

    清楚问题所在: 先开个头,当我们对A进行单元测试时,可能会发现A的实现必须要依赖B.这时,我们在写单元测试时,就必须先创建B的实例,然后把B传给A再建立A的实例进行测试. 这样就会出现一些问题: 1. ...

  10. NUnit+mock+moq单元测试

    [TestFixture] public class InstantBatchBuyTest { private string _mallAbc; private string _itemCode; ...

随机推荐

  1. linux7系统进入单用户模式

    1.重启系统,在出现选择内核界面的时候按“e”键 2.移动光标到红色找到LANG=zh_CN.UTF-8 增加“init=/sysroot/bin/sh” 修改后如下图 3.使用"ctrl+ ...

  2. Axel多线程工具安装

    Axel 是 Linux 下一个不错的轻量级高速下载工具,支持HTTP/FTP/HTTPS/FTPS协议,支持多线程下载.断点续传,且可以从多个地址或者从一个地址的多个连接来下载同一个文件. 大家使用 ...

  3. jmeter压测学习6-HTTP Cookie管理器

    前言 web网站的请求大部分都有cookies,jmeter的HTTP Cookie管理器可以很好的管理cookies. 我用的 jmeter5.1 版本,直接加一个HTTP Cookie管理器放到请 ...

  4. 201871010128-杨丽霞《面向对象程序设计(java)》第十四周学习总结

    201871010128-杨丽霞<面向对象程序设计(java)>第十四周学习总结(1分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-dai ...

  5. 【软件工程1916|W(福州大学)_助教博客】2019年上学期期末问卷调查结果公示

    1.调查问卷概况 福州大学2019W班,收集到有效答卷44份 2. 调查问卷情况 Q1:请问你平均每周在课程上花费多少小时? 去除自估水平超过40小时的,平均16.6H Q2.软工实践的各次作业分别花 ...

  6. datagrid editor动态的改变不同行修改列的editor属性

    onBeforeEdit: function (row) { let options = $(this).treegrid('options'); options.tempeditor = optio ...

  7. n8n 基于node 的流程自动化工具

    n8n 是基于node开发的流程自动化工具,提供了可视化的操作,我们可以用来集成不同的服务. 目前已经提供了很多的服务集成组件,同时我们也可以方便的自己扩展,后边会进行一个系统的 学习,同时介绍下使用 ...

  8. appium--uiautomatorviewer的使用

    uiautomatorviewer的使用 uiautomatorviewer也是获取页面元素属性的工具,相比之前介绍的appium desktop来说,方便了很多,appium desktop需要从启 ...

  9. CSP-S2019游记 执枪的人,一定要做好被杀的觉悟。

    啊,大概是人生中最镇定的三天了. 是了. Day0 教练超级巨,给了我们电话说出去要散养,有事别慌,打电话.身份证丢了别慌,打电话.火车误了别慌,打电话... 然后去了就路上颓颓颓.然后过去试机,打了 ...

  10. oracle--delete truncate drop的区别

    一.delete 1.delete是DML,执行delete操作时,每次从表中删除一行,并且同时将该行的的删除操作记录在redo和undo表空间中以便进行回滚(rollback)和重做操作,但要注意表 ...