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);
Task<bool> DoSomethingAsync();
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
// TryParse方法被调用后将延迟计算返回 true ,out 参数将会被赋值为 "ack" 并返回
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);
// async methods (see below for more about async):
// 异步方法(在下面查看更多关于异步):
mock.Setup(foo => foo.DoSomethingAsync().Result).Returns(true);
这有几个设置异步方法的方式(例如:一个方法返回一个Task或ValueTask):
mock.Setup(foo => foo.DoSomethingAsync().Result).Returns(true);
mock.Setup(foo => foo.DoSomethingAsync()).ReturnAsync(true);
mock.Setup(foo => foo.DoSomethingAsync()).Returns(async () => 42);
// 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):
// 任何通过引用参数传递的值(必须在 Moq4.8 及以上版本):
mock.Setup(foo => foo.Submit(ref It.Ref<Bar>.IsAny)).Returns(true);
// mathcing Func<int>,lazy evaluated
// 配置Func<int>类型的委托,并延迟计算返回
mock.Setup(foo => foo.Add(It.Is<int>(i => i % 2 == 0 ))).Returns(true);
// matching reanges
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");
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"
// 值可以预期的将会设置为"foo"
mock.SetupSet(foo => foo.Name = "foo");
//or verify the setter directly
// 或直接验证设置器
mock.VerifySet(foo => foo.Name = "foo");
// start "tracking" sets/gets to this property
// 开始 跟踪 这个属性的gets和sets
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 changed the initial value
// 新值集可更改初始值
foo.Name = "bar";
Assert.Equal("bar", foo.Name);
mock.SetupAllProperties();
// Setting up an event's `add` and `remove` accessors (requires Moq 4.13 or later):
// 设置一个事件的添加和移除访问器(Moq的版本必须是4.13及以上):
mock.SetupAdd(m => m.FooEvent += It.IsAny<EventHandler>())...;
mock.SetupRemove(m => m.FooEvent -= It.IsAny<EventHandler>())...;
// Raising an event on the mock
// 在模拟时新增一个事件
mock.Raise(m => m.FooEvent += null, new FooEventArgs(fooValue));
//Raising an event on the mock that has sender inhadnler 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
// 调用Submit时导致事件自动触发
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 whick does not adhere to the EventHandler pattern
// 引发自定义事件提示不符合EventHandler模式
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);
var mock = new Mock<IFoo>();
var calls = 0;
var callArgs = new List<string>();
mock.Setup(foo => foo.DoSomething("ping"))
.Callback(() => calls++).Returns(true);
// access invocation arguments
mock.Setup(foo => foo.DoSomething(It.IsAny<string>()))
.Callback((string s) => callArgs.Add(s)).Returns(true);
// alternate equivalent generic method syntax
// 替代等效泛型方法语法
mock.Setup(foo => foo.DoSomething(It.IsAny<string>()))
.Callback<string
mock.Setup(foo => foo.DoSomething(It.IsAny<string>())).Callback<int,string>((i,s) => callArgs.Add(s)).Returns(true);