1. TDD的简介
2.NUnit的介绍
2.1 NUnit的介绍
![](https://confach.cnblogs.com/images/cnblogs_com/confach/NUnit.1.jpg)
![](https://confach.cnblogs.com/images/cnblogs_com/confach/NUnit.2.jpg)
图2 NUnit运行的另外一个效果
2.2 一些常用属性
- Test Fixture
- Test
TestFixtureAttribute
- 必须是Public,否则NUnit看不到它的存在.
- 它必须有一个缺省的构造函数,否则是NUnit不会构造它.
- 构造函数应该没有任何副作用,因为NUnit在运行时经常会构造这个类多次,如果要是构造函数要什么副作用的话,那不是乱了.
1using System;
2using NUnit.Framework;
3namespace MyTest.Tests
4{
5
6[TestFixture]
7public class PriceFixture
8{
9//
10}
11}
12
TestAttribute
public void MethodName()
1using System;
2using NUnit.Framework;
3
4namespace MyTest.Tests
5{
6[TestFixture]
7public class SuccessTests
8{
9[Test] public void Test1()
10{ /*
*/ }
11}
12}
13
14
一般来说,有了上面两个属性,你可以做基本的事情了.
另外,我们再对如何进行比较做一个描述。
在NUnit中,用Assert(断言)进行比较,Assert是一个类,它包括以下方法:AreEqual,AreSame,Equals, Fail,Ignore,IsFalse,IsNotNull,具体请参看NUnit的文档。
3.如何在.NET中应用NUnit
第1步.为测试代码创建一个Visual Studio工程。
![](https://confach.cnblogs.com/images/cnblogs_com/confach/NUnit.3.jpg)
图 4-1: 创建第一个NUnit工程
第2步.增加一个NUnit框架引用
![](https://confach.cnblogs.com/images/cnblogs_com/confach/NUnit.4.jpg)
图 4-2: 增加一个 nunit.framework.dll 引用到工程
第3步.为工程加一个类.
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
5
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
6
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
9
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
12
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
14
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
15
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
16
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
17
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
18
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
19
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
第4步.建立你的Visual Studio 工程,使用NUnit-Gui测试
第5步.编译运行测试.
![](https://confach.cnblogs.com/images/cnblogs_com/confach/NUnit.7.jpg)
图 4-4: 测试程序集的测试在 NUnit-Gui中的视图
4.其他的一些核心概念
SetUp/TearDown 属性
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
5
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
6
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
9
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
12
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
14
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
15
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
16
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
17
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
20
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
21
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
22
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
23
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
24
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
25
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
27
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
28
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
5
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
6
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
9
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
14
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
15
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
16
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
17
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
20
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
21
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
22
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
23
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
24
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
25
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
27
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
28
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
29
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
30
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
31
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
32
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
33
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
这样NUnit将在执行每个测试前执行标记SetUp属性的方法.在本例中就是执行InitializeOperands()方法.记住,这里这个方法必须为public,不然就会有以下错误:Invalid Setup or TearDown method signature
ExpectedException
1[Test]
2[ExpectedException(typeof(DivideByZeroException))]
3public void DivideByZero()
4{
5int zero = 0;
6int infinity = a/zero;
7Assert.Fail("Should have gotten an exception");
8}
9
Ignore 属性
1[Test]
2[Ignore("Multiplication is ignored")]
3public void MultiplyTwoNumbers()
4{
5int product = a * b;
6Assert.AreEqual(2, product);
7}
![](https://confach.cnblogs.com/images/cnblogs_com/confach/NUnit.8.jpg)
图 5-1: 在一个程序员测试中使用 Ignore属性
TestFixtureSetUp/TestFixtureTearDown
1using NUnit.Framework;
2
3[TestFixture]
4public class DatabaseFixture
5{
6[TestFixtureSetUp]
7public void OpenConnection()
8{
9//open the connection to the database
10}
11![]()
12[TestFixtureTearDown]
13public void CloseConnection()
14{
15//close the connection to the database
16}
17![]()
18[SetUp]
19public void CreateDatabaseObjects()
20{
21//insert the records into the database table
22}
23![]()
24[TearDown]
25public void DeleteDatabaseObjects()
26{
27//remove the inserted records from the database table
28}
29![]()
30[Test]
31public void ReadOneObject()
32{
33//load one record using the open database connection
34}
35![]()
36[Test]
37public void ReadManyObjects()
38{
39//load many records using the open database connection
40}
41}
42
43
Test Suite
1
namespace NUnit.Tests
2
{
3
using System;
4
using NUnit.Framework;
5
6![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
public class AllTests
9
{
10
[Suite]
11
public static TestSuite Suite
12
{
13
get
14
{
15
TestSuite suite = new TestSuite("All Tests");
16
suite.Add(new OneTestCase());
17
suite.Add(new Assemblies.AssemblyTests());
18
suite.Add(new AssertionTest());
19
return suite;
20
}
21
}
22
}
23
}
24
Category属性
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
3
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
4
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
5
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
6
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
9
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
10
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
13
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
14
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
15
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
16
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
17
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
20
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
21
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
22
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
23
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
24
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
NUnit-GUI界面如图5-2:1using System;
2using NUnit.Framework;
3![]()
4namespace NUnitQuickStart
5{
6[TestFixture]
7public class NumersFixture
8{
9private int a;
10private int b;
11[SetUp]
12public void InitializeOperands()
13{
14a = 1;
15b = 2;
16}
17![]()
18[Test]
19[Category("Numbers")]
20public void AddTwoNumbers()
21{
22int sum=a+b;
23Assert.AreEqual(sum,3);
24}
25![]()
26[Test]
27[Category("Exception")]
28[ExpectedException(typeof(DivideByZeroException))]
29public void DivideByZero()
30{
31int zero = 0;
32int infinity = a/zero;
33Assert.Fail("Should have gotten an exception");
34}
35[Test]
36[Ignore("Multiplication is ignored")]
37[Category("Numbers")]
38public void MultiplyTwoNumbers()
39{
40int product = a * b;
41Assert.AreEqual(2, product);
42}
43![]()
44}
45
图5-2:使用Catagories属性的界面
Explicit属性
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
5
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
6
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
7
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
9
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
11
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
Expected Exception属性
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
5
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
6
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
9
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
10
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
5 . 测试生命周期合约
1using System;
2using NUnit.Framework;
3[TestFixture]
4public class LifeCycleContractFixture
5{
6[TestFixtureSetUp]
7public void FixtureSetUp()
8{
9Console.Out.WriteLine("FixtureSetUp");
10}
11![]()
12[TestFixtureTearDown]
13public void FixtureTearDown()
14{
15Console.Out.WriteLine("FixtureTearDown");
16}
17![]()
18[SetUp]
19public void SetUp()
20{
21Console.Out.WriteLine("SetUp");
22}
23
24[TearDown]
25public void TearDown()
26{
27Console.Out.WriteLine("TearDown");
28}
29![]()
30[Test]
31public void Test1()
32{
33Console.Out.WriteLine("Test 1");
34}
35
36[Test]
37public void Test2()
38{
39Console.Out.WriteLine("Test 2");
40}
41
42}
43
44
FixtureSetUp
SetUp
Test 1
TearDown
SetUp
Test 2
TearDown
FixtureTearDown
在.NET中如何测试Private和Protected方法?
How to Test Private and Protected methods in .NET, TimStall,
介绍
TDD是1)写测试2)写通过这些测试的代码,3)然后重构的实践.在,NET社区中, 这个概念逐渐变得非常流行,这归功于它所增加的质量保证.此时,它很容易测试public方法,但是一个普遍的问题出现了,”我如何测试Protected和private方法呢?”
本文将:
- 总结”你是否应该测试private方法的争论?”的一些关键点.
- 创建一些案例,这些案例仍旧是有用的,至少知道怎样测试private和protected方法—不考虑你站在争论的哪一边.
- 提供方法和可下载的代码示例来展现这些测试技术.
背后的方法
你是否应该测试private方法?
一个Google查询 向你展示了有很多关于使用private方法的争议,更不用说测试他们了.下面这个表概括了一些关于这个话题的正方和反方的普遍意见.
正方 |
反方 | |
使用private方法 |
|
|
测试Private方法 |
|
|
在这些主题的两方,都有明了并且具有经验的人.因此我不打算,也不期望终结”我是否应该测试private方法”的争论.但是对于双方来说,这里仍有价值来知道如何测试他们,即使你认为private不应该被测试.
- 如果你至少能表现出你可以测试他们,但是你没有这样做(例如,你没有简单的说”不要测试private方法”,因为你不知道如何去测试),你的观点将更加具有说服力.
- 测试非public方法的选择让你明白在你的小组中,什么真正做的最好.
- 只要仍有有效的条件,是值得拥有一种方便的方法来测试他们.
好的原则以及不适当的技术
Andrew Hunt a和 David Thomas在他们的书中Pragmatic Unit Testing in C# with NUnit, 解释到,好的单元测试是ATRIP:
- 自动化(Automatic)
- 彻底(Thorough )
- 可重复(Repeatable)
- 独立(Independent )
- 专业(Professional)
对于测试private/protected方法来说,有另外三个附加原则:
- 透明(Transparency) - 不要改变测试下的系统(System Under Test ,SUT),例如,在产品代码中增加包装的方法.
- 范围(Scope) - 可以在Debug和Release下运行
- 简单(Simplicity) -最小的开销,因此容易修改,并且非常简单引入最小的风险.
记住这些原则,下面是一些不足的策略.
策略 |
问题 |
不要使用任何private方法. |
|
使用指示符 #if DEBUG ... #endif 来包装一个public方法,这个方法然后包装private方法.单元测试现在可以间接访问那些public方法包装的private方法.(这是一种我使用许多次的方法,并且发现它是单调的,不是面向对象的) |
|
Public方法使用[ |
|
创建内部方法来访问private方法.然后在public方法包装那些private方法的程序集的其他地方,创建一个公共的测试类. |
|
测试Protected方法
Protected方法仅仅对于它得继承类可见,因此,对于测试套件来说并不是立即可见的.例如,激射我们想测试来自from ClassLibrary1.MyObject
的方法.
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
3
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
4
![](https://confach.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
5
![](https://confach.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
6
![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
Pragmatic Unit Testing in C# with NUnit一书解释了一个解决方案:创建一个继承自MyObject类的类MyObjectTester,然后创建一个public方法TestMyProtectedMethod
,
这个方法包装了那个
protected
方法
.
例如
,
1
public new string TestMyProtectedMethod(string strInput, int i32Value)
2
{
3
return base.MyProtectedMethod(strInput,
4
i32Value);
5
}
6![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
方法很简单,也遵循所有原则:
原则 |
实现 |
透明 |
通过使用继承,并把 |
范围 |
在本方法中没有任何东西依赖Debug-only技术. |
简单 |
尽管这个方法需要一新的类,以及每个protected 方法的额外public包装方法,但是它是面向对象的,并且使类型安全的. |
测试Private方法
测试private方法需要多做有些工作,但是我们仍可以使用System.Reflection来实现.你可以使用反射来动态访问一种类型的方法, 包括实例和静态private方法的方法.注意访问private方法需要ReflectionPermission,但是对于运行在开发机器或者构建服务器上的单元测试来说,这不是问题.
假设我们想测试来自ClassLibrary1.MyObject
的private方法MyPrivateMethod
:
1
private string MyPrivateMethod(string strInput, DateTime dt, double
2
dbl)
3
{
4
return this.Name + ": " + strInput + ", " +
5
dt.ToString() + ", " + dbl.ToString();
6
}
7![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
一个解决方法是创建一个UnitTestUtilities工程,这个工程有一个helper类通过反射来调用测试方法.例如,供下载的解决方案在UnitTestUtilities.Helper
中有如下方法:
1
public static object RunStaticMethod(System.Type t, string strMethod,
2
object [] aobjParams)
3
{
4
BindingFlags eFlags =
5
BindingFlags.Static | BindingFlags.Public |
6
BindingFlags.NonPublic;
7
return RunMethod(t, strMethod,
8
null, aobjParams, eFlags);
9
} //end of method
10
public static object RunInstanceMethod(System.Type t, string strMethod,
11
object objInstance, object [] aobjParams)
12
{
13
BindingFlags eFlags = BindingFlags.Instance | BindingFlags.Public |
14
BindingFlags.NonPublic;
15
return RunMethod(t, strMethod,
16
objInstance, aobjParams, eFlags);
17
} //end of method
18
private static object RunMethod(System.Type t, string
19
strMethod, object objInstance, object [] aobjParams, BindingFlags eFlags)
20
{
21
MethodInfo m;
22
try
23
{
24
m = t.GetMethod(strMethod, eFlags);
25
if (m == null)
26
{
27
throw new ArgumentException("There is no method '" +
28
strMethod + "' for type '" + t.ToString() + "'.");
29
}
30
31
object objRet = m.Invoke(objInstance, aobjParams);
32
return objRet;
33
}
34
catch
35
{
36
throw;
37
}
38
} //end of method
39![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
Private方法RunMethod
带有一些必要的参数,这些参数是反射需要用来调用一个方法,然后返回值的.它有两个public方法RunStaticMethod
和 RunInstanceMethod
来为静态和实例方法分别包装这.
看看RunMethod
,它首先得到类型的MethodInfo.
因为我们期望它仅为已经存在的方法调用
.
一个空的方法触发一个
Exception
.
一旦我们有
MethodInfo
,我们就可以调用实例化对象提供的方法(static 方法为null)以及参数数组.
我们可以在一个NUnit测试中像下面使用这个Utility:
1
[Test] public void TestPrivateInstanceMethod()
2
{
3
string strExpected = "MyName: Hello, 5/24/2004
4
12:00:00 AM, 2.1";
5
6
ClassLibrary1.MyObject objInstance
7
= new MyObject("MyName");
8
9
object obj =
10
UnitTestUtilities.Helper.RunInstanceMethod(
11
typeof(ClassLibrary1.MyObject), "MyPrivateMethod",
12
objInstance, new object[3] {"Hello",
13
new DateTime(2004,05,24), 2.1});
14
15
string strActual = Convert.ToString(obj);
16
17
Assert.AreEqual(strExpected,strActual);
18
}
19![](https://confach.cnblogs.com/Images/OutliningIndicators/None.gif)
原则 |
实现 |
透明 |
我们仅创建的多余代码; |
范围 |
在本方法中没有任何东西依赖Debug-only技术. |
简单 |
Because the method is being dynamically called, the parameters aren't checked at compile time.本方法可以通过一个简单的调用来调用任何方法.一旦你有 |
总结
关于是否应该测试private方法仍有争论,但是我们有能力去测试他们.我们可以使用继承创建一个继承类
TesterClass
来测试protected方法.这个继承类包装了其基类的protected方法为public.我们可以是哦女冠反射来测试private方法,它能够抽象
到一个
UnitTestUtility
helper类.这些技术都能帮助你改进测试覆盖面. 原文:How to Test Private and Protected methods in .NET, TimStall,
原文转自:http://confach.cnblogs.com/archive/2005/06/20/177817.html
http://confach.cnblogs.com/articles/225502.html
作者:
Milestone |