|
|
|
@ -21,9 +21,12 @@ namespace MoqStudy.Test
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class MoqDemoTest:IDisposable
|
|
|
|
|
{
|
|
|
|
|
//说明:因为是个人学习用,所有注释比较多
|
|
|
|
|
|
|
|
|
|
#region xUnit 初始准备
|
|
|
|
|
Mock<IFoo> mock = new Mock<IFoo>();
|
|
|
|
|
IFoo ifoo;
|
|
|
|
|
delegate void SubmitCallback(ref Bar bar);
|
|
|
|
|
public MoqDemoTest()
|
|
|
|
|
{
|
|
|
|
|
ifoo = mock.Object;
|
|
|
|
@ -196,7 +199,47 @@ namespace MoqStudy.Test
|
|
|
|
|
Assert.Equal(4, ifoo.GetCount());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 重复设置
|
|
|
|
|
/// 后面的设置会覆盖前面的设置
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Method_RepeatSet_Test()
|
|
|
|
|
{
|
|
|
|
|
mock.//首次设置
|
|
|
|
|
Setup(f => f.DoSomething("ping"))
|
|
|
|
|
.Returns(true);
|
|
|
|
|
Assert.True(ifoo.DoSomething("ping"));
|
|
|
|
|
|
|
|
|
|
mock.//重复设置相同参数
|
|
|
|
|
Setup(f => f.DoSomething("ping"))
|
|
|
|
|
.Returns(false);
|
|
|
|
|
|
|
|
|
|
//后面的设置,覆盖前面的设置
|
|
|
|
|
Assert.False(ifoo.DoSomething("ping"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 多次设置同一参数不同值的返回值
|
|
|
|
|
/// 保持多次设置
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Method_MultiSet_Test()
|
|
|
|
|
{
|
|
|
|
|
mock.//设置参数为"ping"
|
|
|
|
|
Setup(f => f.DoSomething("ping"))
|
|
|
|
|
.Returns(true);
|
|
|
|
|
|
|
|
|
|
mock.//设置参数为"xyz"
|
|
|
|
|
Setup(f => f.DoSomething("xyz"))
|
|
|
|
|
.Returns(true);
|
|
|
|
|
|
|
|
|
|
Assert.True(ifoo.DoSomething("ping"));
|
|
|
|
|
Assert.True(ifoo.DoSomething("xyz"));
|
|
|
|
|
|
|
|
|
|
//其它均为false
|
|
|
|
|
Assert.False(ifoo.DoSomething("abc1232"));
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 匹配参数
|
|
|
|
@ -312,97 +355,180 @@ namespace MoqStudy.Test
|
|
|
|
|
/// 设置属性
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Properties_Setup_Test()
|
|
|
|
|
public void Property_Setup_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
var ifoo = mock.Object;
|
|
|
|
|
mock //设置属性值
|
|
|
|
|
.Setup(f => f.Name)
|
|
|
|
|
.Returns("wanggaofeng");
|
|
|
|
|
|
|
|
|
|
//设置属性值
|
|
|
|
|
mock.Setup(f => f.Name).Returns("wanggaofeng");
|
|
|
|
|
Assert.Equal("wanggaofeng", ifoo.Name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 自动模拟多层属性
|
|
|
|
|
/// (递归模拟属性)
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Property_Setup_Recursive_Test()
|
|
|
|
|
{
|
|
|
|
|
mock //自动模拟多层(即递归Mocks)
|
|
|
|
|
.Setup(f => f.Bar.Baz.Name)
|
|
|
|
|
.Returns("Bar.Baz.Name");
|
|
|
|
|
|
|
|
|
|
// auto-mocking hierarchies (a.k.a. recursive mocks)
|
|
|
|
|
// 自动模拟多层(即递归Mocks)
|
|
|
|
|
mock.Setup(f => f.Bar.Baz.Name).Returns("Bar.Baz.Name");
|
|
|
|
|
Assert.Equal("Bar.Baz.Name", ifoo.Bar.Baz.Name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 设置属性:todo SetupSet用法
|
|
|
|
|
/// 验证属性设置
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Properties_SetupSet_Test()
|
|
|
|
|
public void Property_VerifySet_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
var ifoo = mock.Object;
|
|
|
|
|
MockException verifyException = null;
|
|
|
|
|
|
|
|
|
|
//expects an invocation to set the value to "foo"
|
|
|
|
|
//期望将调用值设置为“foo”
|
|
|
|
|
var cc= mock.SetupSet(foo => foo.Name = "foo");
|
|
|
|
|
Assert.Equal("foo", ifoo.Name);
|
|
|
|
|
//不执行,为属性赋指定的值,则验证出现异常
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
//检查代码 foo.Name = "foo" 已经执行过
|
|
|
|
|
mock.VerifySet(foo => foo.Name = "foo");
|
|
|
|
|
|
|
|
|
|
verifyException = null;
|
|
|
|
|
}
|
|
|
|
|
catch (MockException ex)
|
|
|
|
|
{
|
|
|
|
|
verifyException = ex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//验证发生异常
|
|
|
|
|
Assert.NotNull(verifyException);
|
|
|
|
|
|
|
|
|
|
//为属性赋指定的值,验证通过
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
mock //设置属性(loose模式下,可以不设置)
|
|
|
|
|
.Setup(f => f.Name)
|
|
|
|
|
.Returns("bbb");
|
|
|
|
|
|
|
|
|
|
//执行赋值语句
|
|
|
|
|
ifoo.Name = "foo";
|
|
|
|
|
|
|
|
|
|
//检查代码 foo.Name = "foo" 已经执行过
|
|
|
|
|
mock.VerifySet(foo => foo.Name = "foo");
|
|
|
|
|
|
|
|
|
|
verifyException = null;
|
|
|
|
|
}
|
|
|
|
|
catch (MockException ex)
|
|
|
|
|
{
|
|
|
|
|
verifyException = ex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Assert.Equal("bbb", ifoo.Name);
|
|
|
|
|
Assert.Null(verifyException);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 期望(等同于检查),属性已经被设置为指定的值
|
|
|
|
|
/// 用法暂不明确:可以用VerifySet替代本功能
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Property_SetupSet_Test()
|
|
|
|
|
{
|
|
|
|
|
mock //todo:用法不明确,待查
|
|
|
|
|
//可以使用 VerifySet 替代
|
|
|
|
|
.SetupSet(foo => foo.Name = "foo");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Assert.Equal(1,2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 验证设置属性
|
|
|
|
|
/// 用法暂不明确:可以用VerifySet替代本功能
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Properties_SetupGet_Test()
|
|
|
|
|
public void Property_SetupGet_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
var ifoo = mock.Object;
|
|
|
|
|
mock //todo:用法不明确,待查
|
|
|
|
|
.SetupGet(foo => foo.Name);
|
|
|
|
|
|
|
|
|
|
// verify the setter directly
|
|
|
|
|
mock.SetupGet(foo => foo.Name);
|
|
|
|
|
ifoo.Name = "foo";
|
|
|
|
|
Assert.Equal("foo", ifoo.Name);
|
|
|
|
|
Assert.True(1==2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Setup a property so that it will automatically start tracking its value (also known as Stub)
|
|
|
|
|
/// 设置属性以使其自动开始跟踪其值(也称为存根)
|
|
|
|
|
/// 设置后,改变属性值,再次调用时,属性值不变
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Properties_SetupProperty_Test()
|
|
|
|
|
public void Property_Setup_Change_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
mock.Setup(f => f.Name)
|
|
|
|
|
.Returns("ping");
|
|
|
|
|
|
|
|
|
|
// start "tracking" sets/gets to this property
|
|
|
|
|
// 开始“跟踪”设置/获取此属性
|
|
|
|
|
mock.SetupProperty(f => f.Name);
|
|
|
|
|
Assert.Equal("ping", ifoo.Name);
|
|
|
|
|
|
|
|
|
|
// alternatively, provide a default value for the stubbed property
|
|
|
|
|
// 或者,为插入属性提供默认值。
|
|
|
|
|
mock.SetupProperty(f => f.Name, "foo");
|
|
|
|
|
//为属性赋新值
|
|
|
|
|
ifoo.Name = "ack";
|
|
|
|
|
|
|
|
|
|
//再次调用,属性值保持"ping"不变
|
|
|
|
|
Assert.False(ifoo.Name == "ack");
|
|
|
|
|
Assert.True(ifoo.Name == "ping");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now you can do:
|
|
|
|
|
// 现在你可以这么做:
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 重复设置属性
|
|
|
|
|
/// 后面设置的属性值,覆盖前面的设置
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Property_Repeat_Setup_Test()
|
|
|
|
|
{
|
|
|
|
|
mock //设置属性值为 ping
|
|
|
|
|
.Setup(f => f.Name)
|
|
|
|
|
.Returns("ping");
|
|
|
|
|
|
|
|
|
|
IFoo foo = mock.Object;
|
|
|
|
|
// Initial value was stored
|
|
|
|
|
// 初始值被存储
|
|
|
|
|
Assert.Equal("foo", foo.Name);
|
|
|
|
|
Assert.Equal("ping", ifoo.Name);
|
|
|
|
|
|
|
|
|
|
// New value set which changes the initial value
|
|
|
|
|
// 新的设定值改变初始值
|
|
|
|
|
foo.Name = "bar";
|
|
|
|
|
Assert.Equal("bar", foo.Name);
|
|
|
|
|
mock //再次设置属性值为 ack
|
|
|
|
|
.Setup(f => f.Name)
|
|
|
|
|
.Returns("ack");
|
|
|
|
|
|
|
|
|
|
Assert.Equal("ack", ifoo.Name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Stub all properties on a mock (not available on Silverlight)
|
|
|
|
|
/// 存根所有模拟属性
|
|
|
|
|
/// 存根设置的属性值
|
|
|
|
|
/// 设置后自动开始跟踪属性值,为属性赋值后,调用属性值踉着改变
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Properties_SetupAllProperties_Test()
|
|
|
|
|
public void Property_SetupProperty_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
var ifoo = mock.Object;
|
|
|
|
|
mock.SetupAllProperties();
|
|
|
|
|
//注意对比Setup设置:Setup设置的属性,为属性赋新值后,调用属性值保持不变
|
|
|
|
|
|
|
|
|
|
// 设置并开始“跟踪”此属性
|
|
|
|
|
mock.SetupProperty(f => f.Name);
|
|
|
|
|
|
|
|
|
|
// 或者 设置默认值并开始“跟踪”此属性
|
|
|
|
|
mock.SetupProperty(f => f.Name, "foo");
|
|
|
|
|
|
|
|
|
|
// 初始值被存储
|
|
|
|
|
Assert.Equal("foo", ifoo.Name);
|
|
|
|
|
|
|
|
|
|
// 设定新值改,初始值被新值覆盖
|
|
|
|
|
ifoo.Name = "bar";
|
|
|
|
|
Assert.Equal("bar", ifoo.Name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 存根所有模拟属性
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Property_SetupAllProperties_Test()
|
|
|
|
|
{
|
|
|
|
|
mock //存根所有属性,这意味着设置其值将导致它被保存并在请求属性时返回。
|
|
|
|
|
//每个属性值设置为Mock框架的默认值。
|
|
|
|
|
.SetupAllProperties();
|
|
|
|
|
|
|
|
|
|
Assert.Null(ifoo.Name);
|
|
|
|
|
|
|
|
|
|
//赋新值
|
|
|
|
|
ifoo.Name = "change";
|
|
|
|
|
Assert.Equal("change", ifoo.Name);
|
|
|
|
|
}
|
|
|
|
@ -425,11 +551,10 @@ namespace MoqStudy.Test
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Callback_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
var ifoo = mock.Object;
|
|
|
|
|
var calls = 0;
|
|
|
|
|
|
|
|
|
|
mock.Setup(foo => foo.DoSomething("ping"))
|
|
|
|
|
mock //回调函数,返回后,执行其它代码
|
|
|
|
|
.Setup(foo => foo.DoSomething("ping"))
|
|
|
|
|
.Returns(true)
|
|
|
|
|
.Callback(() => calls++);
|
|
|
|
|
|
|
|
|
@ -447,20 +572,17 @@ namespace MoqStudy.Test
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// access invocation arguments
|
|
|
|
|
/// 回调函数中使用参数
|
|
|
|
|
/// 回调函数中使用设置参数
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Callback_Argument_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
var ifoo = mock.Object;
|
|
|
|
|
var callArgs = new List<string>();
|
|
|
|
|
//问题:多次设置,会什么结果
|
|
|
|
|
|
|
|
|
|
mock.Setup(foo => foo.DoSomething(It.IsAny<string>()))
|
|
|
|
|
.Returns(true)
|
|
|
|
|
.Callback((string s) => callArgs.Add(s));
|
|
|
|
|
// 或者如下面泛型用法
|
|
|
|
|
// 或者如下:回调函数的泛型版本
|
|
|
|
|
// .Callback<string>(s => callArgs.Add(s));
|
|
|
|
|
|
|
|
|
|
Assert.True(ifoo.DoSomething("first"));
|
|
|
|
@ -474,16 +596,13 @@ namespace MoqStudy.Test
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// alternate equivalent generic method syntax
|
|
|
|
|
/// 泛型回调函数中使用参数
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Callback_Generic_Argument_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
var ifoo = mock.Object;
|
|
|
|
|
var callArgs = new List<string>();
|
|
|
|
|
//问题:多次设置,会什么结果
|
|
|
|
|
|
|
|
|
|
mock.Setup(foo => foo.DoSomething(It.IsAny<string>()))
|
|
|
|
|
.Returns(true)
|
|
|
|
|
.Callback<string>(s => callArgs.Add(s));
|
|
|
|
@ -499,15 +618,11 @@ namespace MoqStudy.Test
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// access arguments for methods with multiple parameters
|
|
|
|
|
/// 回调函数中使用多个参数
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Callback_MultiArgument_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
var ifoo = mock.Object;
|
|
|
|
|
|
|
|
|
|
var callCount = 0;
|
|
|
|
|
var callArgs = new List<string>();
|
|
|
|
|
|
|
|
|
@ -532,15 +647,11 @@ namespace MoqStudy.Test
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// callbacks can be specified before and after invocation
|
|
|
|
|
/// 指定回调函数位置:前置执行或后置执行
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Callback_BeforeAndAfter_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
var ifoo = mock.Object;
|
|
|
|
|
|
|
|
|
|
var returnBefore = new List<string>();
|
|
|
|
|
var returnAfter = new List<string>();
|
|
|
|
|
|
|
|
|
@ -558,110 +669,125 @@ namespace MoqStudy.Test
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// callbacks for methods with `ref` / `out` parameters are possible but require some work (and Moq 4.8 or later)
|
|
|
|
|
/// 回调函数中使用 re/out 参数
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Callback_RefAndOut_Parameter_Test()
|
|
|
|
|
{
|
|
|
|
|
//var mock = new Mock<IFoo>();
|
|
|
|
|
//mock.Setup(foo => foo.Submit(ref It.Ref<Bar>.IsAny))
|
|
|
|
|
// .Callback
|
|
|
|
|
// (
|
|
|
|
|
// new SubmitCallback
|
|
|
|
|
// (
|
|
|
|
|
// (ref Bar bar) => { bar.Baz.Name = "xyz"; }
|
|
|
|
|
// )
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
//var myBar = new Bar()
|
|
|
|
|
//{
|
|
|
|
|
// Baz=new Baz() { Name="gaofeng"}
|
|
|
|
|
//};
|
|
|
|
|
|
|
|
|
|
//mock.Object.Submit(ref myBar);
|
|
|
|
|
mock //回调函数中使用 re/out 参数
|
|
|
|
|
.Setup(foo => foo.Submit(ref It.Ref<Bar>.IsAny))
|
|
|
|
|
.Callback
|
|
|
|
|
(
|
|
|
|
|
new SubmitCallback
|
|
|
|
|
(
|
|
|
|
|
(ref Bar bar) => { bar.Baz.Name = "xyz"; }
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
var myBar = new Bar()
|
|
|
|
|
{
|
|
|
|
|
Baz = new Baz() { Name = "gaofeng" }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//Assert.Equal("xyz", myBar.Baz.Name);
|
|
|
|
|
mock.Object.Submit(ref myBar);
|
|
|
|
|
|
|
|
|
|
////对比验证
|
|
|
|
|
//var mock2 = new Mock<IFoo>();
|
|
|
|
|
//mock2.Setup(foo => foo.Submit(ref It.Ref<Bar>.IsAny));
|
|
|
|
|
//var myBar2 = new Bar()
|
|
|
|
|
//{
|
|
|
|
|
// Baz = new Baz() { Name = "gaofeng" }
|
|
|
|
|
//};
|
|
|
|
|
Assert.Equal("xyz", myBar.Baz.Name);
|
|
|
|
|
|
|
|
|
|
//mock2.Object.Submit(ref myBar2);
|
|
|
|
|
//和没有回调函数的对比验证
|
|
|
|
|
var mock2 = new Mock<IFoo>();
|
|
|
|
|
mock2.Setup(foo => foo.Submit(ref It.Ref<Bar>.IsAny));
|
|
|
|
|
var myBar2 = new Bar()
|
|
|
|
|
{
|
|
|
|
|
Baz = new Baz() { Name = "gaofeng" }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//Assert.Equal("gaofeng", myBar2.Baz.Name);
|
|
|
|
|
mock2.Object.Submit(ref myBar2);
|
|
|
|
|
|
|
|
|
|
Assert.Equal("gaofeng", myBar2.Baz.Name);
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 验证
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 不设置,进行验证,出现异常
|
|
|
|
|
/// 验证匹配项是否调用
|
|
|
|
|
/// 不设置,验证出现异常
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Verify_NoSetup_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
//验证匹配项是否调用
|
|
|
|
|
Assert.Throws<MockException>(() => mock.Verify(f => f.Add(1)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 设置后,不运行方法进行验证
|
|
|
|
|
/// 验证匹配项是否调用
|
|
|
|
|
/// 设置后不运行,验证出现异常
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Verify_NoRun_Test()
|
|
|
|
|
public void Verify_Setup_NoRun_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
var ifoo = mock.Object;
|
|
|
|
|
mock.Setup(f => f.Add(2)).Returns(true);
|
|
|
|
|
mock //验证匹配项是否调用
|
|
|
|
|
.Setup(f => f.Add(2))
|
|
|
|
|
.Returns(true);
|
|
|
|
|
|
|
|
|
|
Assert.Throws<MockException>(() => { mock.Verify(f => f.Add(2)); });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 验证匹配项是否调用
|
|
|
|
|
/// 设置并调用后,验证通过
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Verify_Test()
|
|
|
|
|
public void Verify_Setup_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
var ifoo = mock.Object;
|
|
|
|
|
mock //设置
|
|
|
|
|
.Setup(f => f.Add(2))
|
|
|
|
|
.Returns(true);
|
|
|
|
|
|
|
|
|
|
mock.Setup(f => f.Add(2)).Returns(true);
|
|
|
|
|
//调用运行
|
|
|
|
|
ifoo.Add(2);
|
|
|
|
|
|
|
|
|
|
//通过验证
|
|
|
|
|
mock.Verify(f => f.Add(2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Verify with custom error message for failure
|
|
|
|
|
/// 在验证失败的时候,提供自定义的错误提示信息
|
|
|
|
|
/// 验证失败时,自定义异常信息
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Verify_ErrorMessage_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
var ifoo = mock.Object;
|
|
|
|
|
Assert.Throws<MockException>(() => { mock.Verify(foo => foo.DoSomething("ping"), "When doing operation X, the service should be pinged always"); });
|
|
|
|
|
MockException mockException = null;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
mock.Verify(foo => foo.DoSomething("ping"), "Custom exception message");
|
|
|
|
|
mockException = null;
|
|
|
|
|
}
|
|
|
|
|
catch (MockException ex)
|
|
|
|
|
{
|
|
|
|
|
mockException = ex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Assert.StartsWith("Custom exception message", mockException.Message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Method should never be called
|
|
|
|
|
/// 方法从未被调用
|
|
|
|
|
/// 验证方法从未被调用
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Verify_Never_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
var ifoo = mock.Object;
|
|
|
|
|
|
|
|
|
|
mock.Verify(foo => foo.DoSomething("ping"), Times.Never());
|
|
|
|
|
|
|
|
|
|
ifoo.DoSomething("ping");
|
|
|
|
|
Assert.Throws<MockException>(()=> {
|
|
|
|
|
mock.Verify(foo => foo.DoSomething("ping"), Times.Never());
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Called at least once
|
|
|
|
|
/// 至少调用过一次
|
|
|
|
|
/// 验证至少调用过一次
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Verify_AtLeastOnce_Test()
|
|
|
|
@ -701,7 +827,6 @@ namespace MoqStudy.Test
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Verify getter invocation, regardless of value
|
|
|
|
|
/// 验证属性被读取过
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
@ -744,7 +869,6 @@ namespace MoqStudy.Test
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Verify setter invocation, regardless of value.
|
|
|
|
|
/// 验证对属性的赋值(已弃用的方法)
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
@ -787,14 +911,11 @@ namespace MoqStudy.Test
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Verify setter invocation, regardless of value
|
|
|
|
|
/// 验证对于属性设置特定的值
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Verify_PropertieValue_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
var ifoo = mock.Object;
|
|
|
|
|
MockException mockException = null;
|
|
|
|
|
var customInfo = "custom info";
|
|
|
|
|
try
|
|
|
|
@ -826,14 +947,11 @@ namespace MoqStudy.Test
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Verify setter with an argument matcher
|
|
|
|
|
/// 验证匹配的参数
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Verify_Propertie_Argument_Test()
|
|
|
|
|
{
|
|
|
|
|
var mock = new Mock<IFoo>();
|
|
|
|
|
var ifoo = mock.Object;
|
|
|
|
|
MockException mockException = null;
|
|
|
|
|
var customInfo = "custom info";
|
|
|
|
|
try
|
|
|
|
@ -894,6 +1012,7 @@ namespace MoqStudy.Test
|
|
|
|
|
/// Callbase
|
|
|
|
|
/// 使用Callbase
|
|
|
|
|
/// 如果没有重写基类的实现,默认将不会调用基类,在 Mock Web/Html 控件的是必须的
|
|
|
|
|
/// http://www.360doc.com/content/14/0729/09/10504424_397815601.shtml
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void CustomMock_Callbase_Test()
|
|
|
|
|