From 097e03e34a705b1efba06e6f7747cb44a80a6e6c Mon Sep 17 00:00:00 2001
From: bicijinlian <bicijinlian@163.com>
Date: Mon, 30 Jul 2018 10:44:34 +0800
Subject: [PATCH] =?UTF-8?q?=E5=85=B6=E5=AE=83=20=E5=AE=8C=E6=88=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 MoqStudy.MockModel/DemoModel/DemoHelper.cs   | 22 +++++++
 MoqStudy.MockModel/MoqStudy.MockModel.csproj |  1 +
 MoqStudy.MockModel/StudyModel/Teacher.cs     | 12 +++-
 MoqStudy.Test/MoqDemoTest.cs                 | 66 +++++++++++++++++---
 4 files changed, 90 insertions(+), 11 deletions(-)
 create mode 100644 MoqStudy.MockModel/DemoModel/DemoHelper.cs

diff --git a/MoqStudy.MockModel/DemoModel/DemoHelper.cs b/MoqStudy.MockModel/DemoModel/DemoHelper.cs
new file mode 100644
index 0000000..c8a1c66
--- /dev/null
+++ b/MoqStudy.MockModel/DemoModel/DemoHelper.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MoqStudy.MockModel
+{
+    public class DemoHelper
+    {
+    }
+
+    public interface CommandBaseProtectedMembers
+    {
+        bool Execute(string arg);
+    }
+
+    public interface TeacherDoubling
+    {
+        decimal Doubling(decimal number);
+    }
+}
diff --git a/MoqStudy.MockModel/MoqStudy.MockModel.csproj b/MoqStudy.MockModel/MoqStudy.MockModel.csproj
index 9258221..6b3a3a4 100644
--- a/MoqStudy.MockModel/MoqStudy.MockModel.csproj
+++ b/MoqStudy.MockModel/MoqStudy.MockModel.csproj
@@ -46,6 +46,7 @@
     <Compile Include="DemoModel\Bar.cs" />
     <Compile Include="DemoModel\Baz.cs" />
     <Compile Include="DemoModel\CallBaseHelper.cs" />
+    <Compile Include="DemoModel\DemoHelper.cs" />
     <Compile Include="DemoModel\IFoo.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="StudyModel\Teacher.cs" />
diff --git a/MoqStudy.MockModel/StudyModel/Teacher.cs b/MoqStudy.MockModel/StudyModel/Teacher.cs
index 3f20a57..b53baa9 100644
--- a/MoqStudy.MockModel/StudyModel/Teacher.cs
+++ b/MoqStudy.MockModel/StudyModel/Teacher.cs
@@ -23,9 +23,9 @@ namespace MoqStudy.MockModel
             return Id + GroupId;
         }
 
-        protected virtual int GetAge(int age)
+        protected virtual decimal Doubling(decimal number)
         {
-            return age + 2;
+            return number * 2;
         }
 
         protected virtual bool Execute(int number)
@@ -36,5 +36,13 @@ namespace MoqStudy.MockModel
             }
             return number % 2 == 0;
         }
+
+        /// <summary>
+        /// 运行私有方法
+        /// </summary>
+        public virtual bool CompareWithDoubling(decimal number)
+        {
+            return number > Doubling(number);
+        }
     }
 }
diff --git a/MoqStudy.Test/MoqDemoTest.cs b/MoqStudy.Test/MoqDemoTest.cs
index a0e6166..bcfd928 100644
--- a/MoqStudy.Test/MoqDemoTest.cs
+++ b/MoqStudy.Test/MoqDemoTest.cs
@@ -1138,25 +1138,73 @@ namespace MoqStudy.Test
         [Fact]
         public void Miscellaneous_Protected_Test()
         {
-            //todo:用法还不清楚
-            var mock = new Mock<Teacher>();
+            var mock = new Mock<Teacher>() { CallBase = true };
+            var protectValue = 5;
             mock.Protected()
-                 .Setup<int>("GetAge",2)
-                 .Returns(5);              
-            //todo:设置好了,怎么使用是个问题
+                .Setup<decimal>("Doubling", It.IsAny<decimal>())
+                .Returns(protectValue);
 
-            // 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)
+            // 如果用到了参数匹配, 必须使用 ItExpr 来代替 It 
+            // 以后计划改进 
             mock.Protected()
                 .Setup<bool>("Execute", ItExpr.IsAny<int>())
                 .Returns(true);
+
+            //注意使用方法:
+            //设置模拟对象的保护成员后,直接访问不了(保护级别限制)
+            // 使用验证方法进行验证,或者在其它设置里直接使用保护方式的变量结果。
+            mock.Setup(t => t.CompareWithDoubling(It.IsAny<decimal>()))
+                .Returns((decimal p)=> { return p > protectValue; });
+
+            var runValue1 = mock.Object.CompareWithDoubling(1);
+            var runValue3 = mock.Object.CompareWithDoubling(3);
+            var runValue5 = mock.Object.CompareWithDoubling(5);
+
+            var runValue7 = mock.Object.CompareWithDoubling(7);
+
+            Assert.False(runValue1);
+            Assert.False(runValue3);
+            Assert.False(runValue5);
+            Assert.True(runValue7);
+        }
+
+        /// <summary>
+        /// 接口方式,设置保护成员
+        /// 4.8及更高版本
+        /// </summary>
+        [Fact]
+        public void Miscellaneous_Protected_UseInterface_Test()
+        {
+            var mock = new Mock<Teacher>() { CallBase = true };
+            var protectValue = 5;
+            mock //保护方法转为接口,进行设置
+                .Protected()
+                .As<TeacherDoubling>()
+                .Setup(m=>m.Doubling(It.IsAny<decimal>()))
+                .Returns(protectValue);
+
+            //注意使用方法:
+            //设置模拟对象的保护成员后,直接访问不了(保护级别限制)
+            // 使用验证方法进行验证,或者在其它设置里直接使用保护方式的变量结果。
+            mock.Setup(t => t.CompareWithDoubling(It.IsAny<decimal>()))
+                .Returns((decimal p) => { return p > protectValue; });
+
+            var runValue1 = mock.Object.CompareWithDoubling(1);
+            var runValue3 = mock.Object.CompareWithDoubling(3);
+            var runValue5 = mock.Object.CompareWithDoubling(5);
+
+            var runValue7 = mock.Object.CompareWithDoubling(7);
+
+            Assert.False(runValue1);
+            Assert.False(runValue3);
+            Assert.False(runValue5);
+            Assert.True(runValue7);
         }
         #endregion
 
         #region 高级特性
         [Fact]
-        public void Advanced_GetFromMocked_Test()
+        public void Advanced_GetMockFromMocked_Test()
         {
             // get mock from a mocked instance
             IFoo foo =new Mock<IFoo>().Object; // get mock instance somehow 以某种方式获取模拟实例