MoqDemo update

develop
bicijinlian 7 years ago
parent a1cf8f3a22
commit d2b37932bb

@ -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 //回调函数中使用 re/out 参数
.Setup(foo => foo.Submit(ref It.Ref<Bar>.IsAny))
.Callback
(
new SubmitCallback
(
(ref Bar bar) => { bar.Baz.Name = "xyz"; }
)
);
//mock.Object.Submit(ref myBar);
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()

Loading…
Cancel
Save