Telerik JustMock?下载30天免费试用

模拟非公共成员和类型

本文提供各种示例,演示如何模拟与的非公共成员和类型Telerik®JustMock

简介

可以使用JustMock在提升模式下模拟非公共成员和类型。当你想隔离对非公共成员和类型的调用时,这很有用,例如:

  • 私有调用、方法和接口
  • 私有静态方法和属性
  • 保护成员
  • 内部类
  • 内部虚方法和属性

此特性仅在Telerik JustMock的商业版本中可用。指主题,以了解更多关于商业版本和免费版本之间的差异。

如果您需要一个完整的Visual Studio项目来演示如何模拟非公共成员和类型,请参考安装目录中的示例。默认安装目录为C:\Program Files (x86)\Progress\Telerik JustMock\示例

先决条件

在接下来的例子中,我们将使用下面的示例类进行测试:

示例设置

公共类Foo{私有void DoPrivate(){抛出新的NotImplementedException();} private void DoPrivate(int arg){抛出新的NotImplementedException();}公共无效dopubpublic () {doprivprivate ();} private void DoPrivateGeneric(T arg){抛出新的NotImplementedException();}公共无效dopubicgeneric (T arg) {DoPrivateGeneric(arg);}公共无效执行(int arg) {DoPrivate(arg);} private int PrivateEcho(int arg){返回参数;} public int Echo(int arg){返回PrivateEcho(arg);}内部虚拟无效Do(){抛出新的NotImplementedException();}内部虚拟字符串值{get{抛出新的NotImplementedException(); } set { throw new NotImplementedException(); } } private static int PrivateStaticProperty { get; set; } public int GetMyPrivateStaticProperty() { return PrivateStaticProperty; } }
公共类私人子DoPrivate Foo()抛出新的NotImplementedException()结束子私人潜艇DoPrivate (arg整数)把新NotImplementedException()结束子公共子DoPublic () DoPrivate()结束子私人潜艇DoPrivateGeneric (T)(按值传递参数T)把新NotImplementedException()结束子公共子DoPublicGeneric (T)(按值传递参数T) DoPrivateGeneric (T) (arg)结束子公共子执行(arg整数)DoPrivate (arg)结束子私人函数PrivateEcho (arg整数)End Function Public Function Echo(arg As Integer) As Integer Return PrivateEcho(arg) End Function Friend Overridable Sub抛出新的NotImplementedException()结束子朋友重写的属性值()作为字符串得到抛出新的NotImplementedException()结束获得组(值作为字符串)把新NotImplementedException()端设置端财产私有共享财产PrivateStaticProperty()随着整数返回m_PrivateStaticProperty最终得到设置(值为整数)m_PrivateStaticProperty =值端设置端财产私有共享m_PrivateStaticProperty整数公共函数GetMyPrivateStaticProperty()为整数返回PrivateStaticProperty结束函数结束类

重要的

要模拟非公共成员和类型,首先需要从菜单中启用JustMock,从而进入提升模式。学习如何在如何启用/禁用Telerik JustMock的话题。

步骤描述

下面的列表描述了模拟一个非公共成员应该执行的步骤:

  1. 创建要测试的类型的实例。
  2. 使用模拟。非公开修饰符来模拟非公共成员。
  3. 添加安排语句:
    1. 将目标对象传递给测试。
    2. 参数传递要测试的成员名字符串
    3. 如果您测试一个方法,请传递参数。

示例1控件的调用DoPrivate方法喷火类必须设置一个局部变量被称为.通过这种方式,您可以使用指定的方法行为覆盖原始的方法行为。

例1:改变一个私有方法的行为

[TestMethod]公共无效ShouldInvokeNonPublicMember() {Foo Foo = new Foo();Bool called = false;//安排Mock.NonPublic。Arrange(foo, "DoPrivate").DoInstead(() => called = true);//行为foo. dopubpublic ();// Assert. istrue(被调用);}
 Public Sub ShouldInvokeNonPublicMember() Dim foo As New foo () Dim called As Boolean = False '安排Mock.NonPublic。Arrange(foo, "DoPrivate").DoInstead(Sub() called = True) 'Act foo. dopubpublic () 'Assert Assert. istrue (called)结束子

模拟。非公开也可以用来模拟泛型的非公共方法。除了非泛型方法mock之外,还必须在排列中提供泛型类型参数。

例2:改变一个泛型非公共方法的行为

[TestMethod]公共无效ShouldInvokeNonPublicGenericMember() {Foo Foo = new Foo();Bool called = false;//安排Mock.NonPublic。Arrange(foo, "DoPrivateGeneric", new Type[] {typeof(int)}, 10).DoInstead(() => called = true);// Act foo.DoPublicGeneric(10);// Assert. istrue(被调用);}
 Public Sub ShouldInvokeNonPublicGenericMember() Dim foo As foo = New foo () Dim called As Boolean = False '安排Mock.NonPublic。Arrange(foo, "DoPrivateGeneric", New Type() {GetType(Integer)}, 10).DoInstead(Sub() called = True) 'foo。做PublicGeneric(Of Integer)(10) ' Assert Assert.IsTrue(called) End Sub

私有成员

带参数的私有方法

示例3演示如何安排对接受与任何整数值匹配的参数的私有方法的调用。该示例安排PrivateEcho返回1当用any调用时int参数。在表演阶段,PrivateEcho方法调用时使用5作为参数。

有关在模拟时如何使用参数的详细信息,请查看匹配器帮助主题。

例3:用参数改变一个非公共方法的行为

[TestMethod]公共无效ShouldInvokeNonPublicMemberWithMatcher() {Foo Foo = new Foo();Int期望= 1;//安排// PrivateEcho在使用int参数Mock.NonPublic调用时总是返回1。Arrange(foo, "PrivateEcho", argr . express . isany ()).Returns(expected);// Act int actual = foo.Echo(5);// Assert。AreEqual(预期,实际);}
 Public Sub ShouldInvokeNonPublicMemberWithMatcher() Dim foo As New foo () Dim expected As Integer = 1 ' Arrange ' PrivateEcho在使用int参数Mock.NonPublic调用时将始终返回1。排列(Of Integer)(foo, "PrivateEcho", Arg.Expr.)IsAny(Of Integer)()).Returns(expected) 'Act Dim actual As Integer = foo.Echo(5) '维护维护。AreEqual(expected, actual)结束Sub

带有重载的私有方法

在本节中,您将了解如何安排对带有两个重载的私有方法.以下面的类为例:

示例设置

内部类FooInternal{私有无效pExecute(int arg1){抛出新的NotImplementedException();}私有无效pExecute(){抛出新的NotImplementedException();}公共无效执行(int arg1) {pExecute(arg1);}公共无效Execute() {pExecute();}}
友类FooInternal Private Sub pExecute(arg1 As Integer)抛出新的NotImplementedException()结束Sub Private Sub pExecute()抛出新的NotImplementedException()结束Sub Public Sub Execute(arg1 As Integer) pExecute(arg1)结束Sub Public Sub Execute() pExecute()结束Sub

结束课

重要的

要与非公共类交互,必须添加InternalVisibleTo属性。AssemblyInfo.cs在你需要测试的项目中,像这样:

[组装:InternalsVisibleTo(“YourTestProject”)]

在上面所示的示例设置中,pExecute方法有两个重载——一个没有参数,一个接受整数值作为参数。中的代码示例4对象的重载整数.该方法的行为被安排为将局部布尔变量设置为真正的一旦它被调用10作为参数。之后,它通过调用进行操作foo.Execute (10)然后进行验证被称为真正的

示例4:带有重载的模拟私有方法

[TestMethod]公共无效ShouldInvokeNonPublicMemberWithOverloads() {FooInternal foo = new FooInternal();bool isCalled = false;//安排Mock.NonPublic。Arrange(foo, "pExecute", 10).DoInstead(() => isCalled = true);//执行foo.Execute(10);// Assert. istrue (isCalled);}
_公共子ShouldInvokeNonPublicMemberWithOverloads() '将Dim foo安排为新的FooInternal() Dim isCalled As Boolean = False '安排Mock.NonPublic。Arrange(foo, "pExecute", 10).DoInstead(Sub() isCalled = True) '执行(10)Assert. isstrue (isCalled)结束Sub

接口方法的私有实现

本节展示如何从当前类或基类模拟显式(非公共)接口实现方法。

将使用以下类:

示例设置

公共接口IManager {object Provider {get;}}公共类FooBase: IManager{对象IManager。Provider {get{抛出新的NotImplementedException();}}}公共类Bar: FooBase{//…}
公共接口IManager只读属性提供程序()作为对象端接口公共类FooBase实现IManager私有只读属性提供程序()作为对象实现IManager。Provider Get Throw New NotImplementedException() End Get End属性End Class Public Class Bar继承FooBase '…结束课

从上面的示例中可以看到IManager接口定义提供者属性中实现的FooBase.但是,我们需要测试的具体实现位于酒吧类,该类使用FooBase。提供者财产。在示例5你会看到你可以如何嘲笑提供者财产。

例5:模拟接口中定义的私有方法的实现

[TestMethod]公共无效ShouldMockPrivateInterfaceImplementationMethod() {const string expected = "dummy";//排列var bar = Mock.Create< bar >();Mock.Arrange(() => ((IManager)bar).Provider).Returns(预期);//执行,断言。AreEqual(预期,((IManager)栏)”);}
_ Public Sub ShouldMockPrivateInterfaceImplementationMethod() Const expected As String = "dummy" '排列Dim bar = Mock。Create(Of Bar)() Mock.Arrange(Function() DirectCast(Bar, IManager).Provider).Returns("dummy") '行动,断言。AreEqual(expected, DirectCast(bar, IManager).Provider

内部虚拟成员

内部虚法

模拟内部虚拟方法使用类似于模拟公共成员的方法。来演示如何使用JustMock要模拟内部虚方法,我们将使用本主题开头示例设置中的方法。

示例6:模拟内部虚方法

[TestMethod] public void ShouldMockInternalVirtualMethod() {Foo Foo = new Foo();bool isCalled = false;//排列Mock.Arrange(() => foo.Do()).DoInstead(() => isCalled = true);//行为foo.Do();// Assert. istrue (isCalled);}
_ Public Sub ShouldMockInternalVirtualMethod() Dim foo As New foo () Dim isCalled As Boolean = False '安排Mock.Arrange(Sub() foo. do ()).DoInstead(Sub() isCalled = True) 'foo。` Assert Assert. istrue (isCalled)结束Sub

注意,在arrange语句中,它没有使用mock喷火,而是实际的实例。

内部虚拟属性获取和设置

安排内部虚拟财产也类似于安排公共财产。

示例7:模拟内部虚拟属性获取

[TestMethod]公共无效ShouldMockInternalVirtualPropertyGET() {Foo Foo = new Foo();//排列Mock.Arrange(() => foo.Value).Returns("ping");// Act字符串actual = foo.Value;// Assert。AreEqual(“平”,实际);}
_ Public Sub ShouldMockInternalVirtualPropertyGET() Dim foo As New foo () '排列Mock.Arrange(Function() foo.Value).Returns("ping") '将Dim实际作为字符串= foo。值` Assert Assert。AreEqual("ping", actual)结束Sub

注意,在arrange语句中,它没有使用mock喷火,而是实际的实例。

下面的代码是模拟内部虚拟属性集的示例。的方法重写了实际的实现foo。价值必须用某个值调用。

例8:模拟内部虚拟属性集

[TestMethod] public void ShouldMockInternalVirtualPropertySET(){//排列Foo Foo = Mock.Create();Mock.ArrangeSet(() => foo。价值= "ping").MustBeCalled(); // Act foo.Value = "ping"; // Assert Mock.Assert(foo); }
_公共子ShouldMockInternalVirtualPropertySET() '安排Dim foo作为foo = Mock。创建(Of Foo)() Mock.ArrangeSet(Sub() foo.Value = "ping").MustBeCalled() ' Act foo.Value = "ping" ' Assert Mock.Assert(foo) End Sub

私有静态成员

私有静态方法

下面的示例演示如何模拟私有静态方法.我们使用下面的示例类:

示例设置

内部类FooInternalStatic{私有静态int EchoPrivate(int arg1){抛出新的NotImplementedException();} public static int Echo(int arg1){返回echoprivprivate (arg1);} private static int EchoPrivateGeneric(T arg1) {throw new NotImplementedException();} public static int EchoGeneric(T arg1){返回EchoPrivateGeneric(arg1);}}
友类FooInternalStatic私有共享函数EchoPrivate(arg1 As Integer) As Integer Throw New NotImplementedException() End函数公共共享函数Echo(arg1 As Integer) As Integer Return EchoPrivate(arg1) End函数私有共享函数EchoPrivateGeneric(Of T)(ByVal arg1 As T) As Integer Throw New NotImplementedException() End函数公共共享函数EchoGeneric(Of T)(ByVal arg1 As T) As Integer Return EchoPrivateGeneric(Of T)(arg1) End函数结束类

重要的

要与非公共类交互,应该添加InternalVisibleTo属性。AssemblyInfo.cs在你需要测试的项目中,像这样:

[组装:InternalsVisibleTo(“YourTestProject”)]

方法安排在例9FooInternalStatic.EchoPrivate ()

例9:模拟私有静态方法

[TestMethod] public void ShouldMockPrivateStaticMethod(){//安排Mock.NonPublic。排列(" echoprivprivate ", 10);// Act FooInternalStatic.Echo(10);// Assert Mock.NonPublic。Assert(" echoprivprivate ", 10);}
_公共子ShouldMockPrivateStaticMethod() '安排Mock.NonPublic。排列(Of FooInternalStatic, Integer)(" echoprivprivate ", 10) 'Act FooInternalStatic.Echo(10) '断言Mock.NonPublic。Assert(Of FooInternalStatic, Integer)(" echoprivprivate ", 10)结束子

中的代码例9调用回声方法,但其实现调用EchoPrivate方法,因此断言将通过。

与非公共实例泛型方法一样,模拟。非公开可用于模拟非公共静态泛型。

例10:模拟非公共静态泛型方法

[TestMethod] public void ShouldMockPrivateStaticGenericMethod(){//安排Mock.NonPublic。排列("EchoPrivateGeneric", new Type[] {typeof(int)}, 10);// Act FooInternalStatic.EchoGeneric(10);// Assert Mock.NonPublic。Assert("EchoPrivateGeneric", new Type[] {typeof(int)}, 10);}
 Public Sub ShouldMockPrivateStaticGenericMethod() '安排Mock.NonPublic。Arrange(Of FooInternalStatic, Integer)("EchoPrivateGeneric", New Type() {GetType(Integer)}, 10) 'FooInternalStatic行动。回声Generic(Of Integer)(10) ' Assert Mock.NonPublic.Assert(Of FooInternalStatic, Integer)("EchoPrivateGeneric", New Type() {GetType(Integer)}, 10) End Sub

私有静态属性

类的get函数,本节演示如何模拟私有静态属性.的喷火上面定义的类用作示例设置。

财产安排在例11Foo。PrivateStaticProperty.当调用它时,它将返回一个期望的整数值,与默认值不同。

例11:模拟私有静态属性

[TestMethod]公共无效ShouldMockPrivateStaticProperty() {var expected = 10;//排列Foo Foo = new Foo();Mock.NonPublic.Arrange < int > (typeof (Foo),“PrivateStaticProperty”).Returns(预期);// Act int actual = foo.GetMyPrivateStaticProperty();// Assert。AreEqual(预期,实际);}
_ Public Sub ShouldMockPrivateStaticProperty() Dim expected = 10 '将Dim foo安排为New foo () Mock.NonPublic。排列(Of Integer)(GetType(Foo), "PrivateStaticProperty").Returns(expected) 'Act Dim actual As Integer = foo.GetMyPrivateStaticProperty() '维护维护。AreEqual(expected, actual)结束Sub

为了行动,代码调用GetMyPrivateStaticProperty ()方法,但其实现返回PrivateStaticProperty,因此断言通过。

保护成员

为了演示如何模拟受保护的成员,我们将使用以下类:

示例设置

公共类FooWithProtectedMembers{受保护的虚拟无效加载(){抛出新的NotImplementedException();} protected virtual int IntValue {get {throw new NotImplementedException();}} public virtual void Init() {Load();}}
Public Class FooWithProtectedMembers Protected Overridable Sub Load() Throw New NotImplementedException() End Sub Protected Overridable ReadOnly Property IntValue() As Integer Get Throw New NotImplementedException() End Get End Property Public Overridable Sub Init() Load() End Sub

结束课

要模拟JustMock中受保护的成员,可以使用与本主题前面介绍的其他非公共类型相同的方法和逻辑。

首先,我们将安排我们的IntValue ()方法绝对不能发生::

例12:安排受保护方法

[TestMethod]公共无效ShouldAssertOccrenceForNonPublicFunction() {var foo = Mock.Create(Behavior.CallOriginal);Mock.NonPublic.Assert(foo, "IntValue", Occurs.Never()); }
_ Public Sub ShouldAssertOccrenceForNonPublicFunction() Dim foo = Mock。创建(Of FooWithProtectedMembers)(Behavior.CallOriginal) Mock.NonPublic。Assert(Of Integer)(foo, "IntValue", Occurs.Never())结束Sub

第二个测试将测试是否受保护Load ()方法实际被调用时Init ()就会启动。

例13:安排一个受保护的方法必须至少被调用一次

[TestMethod]公共无效ShouldMockProtectedVirtualMembers() {var foo = Mock.Create(Behavior.CallOriginal);Mock.NonPublic.Arrange(foo, "Load").MustBeCalled(); foo.Init(); Mock.Assert(foo); }
_ Public Sub ShouldMockProtectedVirtualMembers() Dim foo = Mock。创建(Of FooWithProtectedMembers)(Behavior.CallOriginal) Mock.NonPublic。Arrange(foo, "Load"). mustbeccalled () foo. init () Mock.Assert(foo)结束Sub

重要的

若要模拟受保护类型,程序集名称必须根据框架设计规则完全限定,即。程序集名称= namespace.注意,您不能模仿的类型mscorlib这样。

内部类

让我们看一个如何模拟. net内部类的示例。考虑到System.Net.HttpRequestCreator类,它是内部的,但有一个公共接口System.Net.IWebRequestCreate例14嘲笑它创建方法。

例14:模拟内部类

[TestMethod] public void ShouldMockInternaldotNETClass(){//排列字符串typeName = "System.Net.HttpRequestCreator";var httpRequestCreator = Mock.Create(typeName);bool isCalled = false;Mock.NonPublic.Arrange(httpRequestCreator, "Create", Arg.Expr.IsAny()).DoInstead(() => isCalled = true); // Act System.Net.IWebRequestCreate iWebRequestCreate = (System.Net.IWebRequestCreate)httpRequestCreator; iWebRequestCreate.Create(new Uri("//www.aliitrade.com"));// Assert. istrue (isCalled);}
_公共子ShouldMockInternaldotNETClass() '将Dim typeName设为字符串= "System.Net. "HttpRequestCreator" Dim HttpRequestCreator = Mock.Create(typeName) Dim isCalled As Boolean = False Mock.NonPublic。排列(httpRequestCreator, "Create", Arg.Expr。IsAny(Of Uri)()).DoInstead(Sub() isCalled = True) '作为System.Net.IWebRequestCreate = DirectCast(httpRequestCreator, System.Net.IWebRequestCreate) iWebRequestCreate。新建(Uri(“//www.aliitrade.com“))Assert. isstrue (isCalled)结束Sub

注意使用Uri Arg.Expr.IsAny < > ()-当我们模拟一个非公共调用时,我们需要知道参数的类型来解析方法。因此,而不是使用参数,就像我们在大多数其他情况下所做的一样,我们必须使用参数。Expr

重要的

要模拟内部类型,程序集名称必须根据框架设计规则完全限定,即。程序集名称= namespace.注意,您不能模仿的类型mscorlib这样。JustMock像上面的例子一样执行分层搜索来找到合适的限定名称。System.Net.HttpRequestCreator系统组装,而不是在系统。网

例15演示如何处理更复杂的场景——通过使用参数调用原始构造函数来模拟内部类,然后从公共接口调用原始实现。出于本例的目的,它将使用另一个内部类-System.Net.WebSocketHttpRequestCreator——派生自公共接口System.Net.IWebRequestCreate

样例测试验证调用是否创建方法,并返回网络。网络Request对象的期望值RequestUri属性集。

例15:使用构造函数参数对内部.NET类进行复杂模拟

[TestMethod] public void ShouldMockInternaldotNETClassWithArgs(){//排列字符串typeName = "System.Net.WebSocketHttpRequestCreator";var httpRequestCreator = Mock。创建(typeName, (config) => config .CallConstructor(new object[] {true})); Mock.NonPublic.Arrange(httpRequestCreator, "Create", Arg.Expr.IsAny()) .CallOriginal() .MustBeCalled(); // Act System.Net.IWebRequestCreate iWebRequestCreate = (System.Net.IWebRequestCreate)httpRequestCreator; var result = iWebRequestCreate.Create(new Uri("//www.aliitrade.com"));// Assert Mock.Assert(httpRequestCreator);断言。AreEqual(新Uri(“//www.aliitrade.com”),result.RequestUri);}
 Public Sub ShouldMockInternaldotNETClassWithArgs() '将Dim typeName设为字符串= "System.Net. "网络SocketHttpRequestCreator" Dim httpRequestCreator = Mock.Create(typeName, Sub(config) _ config.CallConstructor(New Object() {True})) Mock.NonPublic.Arrange(httpRequestCreator, "Create", Arg.Expr.IsAny(Of Uri)()) _ .CallOriginal() _ .MustBeCalled() ' Act Dim iWebRequestCreate As System.Net.IWebRequestCreate = DirectCast(httpRequestCreator, System.Net.IWebRequestCreate) Dim result = iWebRequestCreate.Create(New Uri("//www.aliitrade.com“))Assert(httpRequestCreator)AreEqual(新Uri(“//www.aliitrade.com), result.RequestUri)结束Sub

使用动态包装器进行模拟

JustMock利用。net 4和DLR以允许您将非公共实现包装在动态对象,并尽可能自然地安排它们,就像你可以对公共成员做的那样。

示例16展示如何将模拟实例包装在动态对象中Mock.NonPublic.Wrap ().包装器可以传递给Mock.NonPublic.Arrange而且Mock.NonPublic.Assert与一个操作一起指定要安排的内容。你也可以安排:

  • 属性getter的值
  • 属性setter的动作

参数匹配器使用参数。Expr

在Visual c#项目中使用动态表达式时,应该引用微软。CSharp组装。

例16:使用动态包装器

[TestMethod]公共无效ShouldInvokeNonPublicMemberDynamic() {Foo Foo = new Foo();//动态排列fooAcc = Mock.NonPublic.Wrap(foo);Mock.NonPublic.Arrange < int > (fooAcc.PrivateEcho (Arg.Expr.IsAny < int > ())) .Returns (10);Mock.NonPublic.Arrange <字符串> (fooAcc.Value) .Returns (" foo ");Mock.NonPublic.Arrange (fooAcc。Value = "abc").OccursOnce();// Act var actual = foo.Echo(5);var值= foo.Value;foo。Value = "abc";// Assert。AreEqual(10, actual); Assert.AreEqual("foo", value); Mock.Assert(foo); }
 Public Sub ShouldInvokeNonPublicMemberDynamic() Dim foo As New foo () '将Dim fooAcc排列为Object = Mock.NonPublic. wrap (foo)安排(整数)(fooAcc.PrivateEcho (Arg.Expr。IsAny(Of Integer)()) . returns (10) Mock.NonPublic。Arrange(Of String)(fooAcc. value). returns ("foo")Value = "abc").OccursOnce() 'Act Dim actual As Integer = foo. echo (5) Dim value As String = foo。值foo。价值= "abc" ' Assert Assert.AreEqual(10, actual) Assert.AreEqual("foo", value) Mock.Assert(foo) End Sub
在本文中
Baidu
map