my nunit tips
背景说明:
1、作者使用的单元测试工具是NUnit2.4.3,.Net framework 2.0
2、为了说话方便,下文把被测试的类型统称为T,测试类统称为C,被模拟的类型统称为M。
1、测试事件处理方法
考虑下面T的实现
在测试代码中,作者使用DynamicMock来做测试。但是DynamicMock无法模拟事件的触发,所以不能直接进行测试。那么通常的测试方法是分为两步:
第一步,测试事件是否被正确挂接和移除。
例如,我们要测试M上的一个事件E是否被T正确挂接和移除。Delegate对象的+=和-=运算符被映射为一对方法add_XXX和remve_XXX。
在C中的测试代码可以是:
![]()
{
DynamicMock mMock = new DynamicMock(typeof (M));
T t = new T();
![]()
mMock.Expect("add_E");
t.Foo((M)mMock.MockInstance);
mMock.Verify();
![]()
mMock.Expect("remove_E");
t.Bar((M)mMock.MockInstance);
mMock.Verify();
}
1、作者使用的单元测试工具是NUnit2.4.3,.Net framework 2.0
2、为了说话方便,下文把被测试的类型统称为T,测试类统称为C,被模拟的类型统称为M。
1、测试事件处理方法
考虑下面T的实现
1
class T
2
{
3
public void Foo(M m)
4
{
5
m.E += OnE();
6
}
7![]()
8
public void Bar(M m)
9
{
10
m.E -= OnE();
11
}
12![]()
13
private void OnE()
14
{ /*do something here*/ }
15
}
class T2
{3
public void Foo(M m)4
{5
m.E += OnE();6
}7

8
public void Bar(M m)9
{10
m.E -= OnE();11
}12

13
private void OnE()14
{ /*do something here*/ }15
}在测试代码中,作者使用DynamicMock来做测试。但是DynamicMock无法模拟事件的触发,所以不能直接进行测试。那么通常的测试方法是分为两步:
第一步,测试事件是否被正确挂接和移除。
例如,我们要测试M上的一个事件E是否被T正确挂接和移除。Delegate对象的+=和-=运算符被映射为一对方法add_XXX和remve_XXX。
在C中的测试代码可以是:

{
DynamicMock mMock = new DynamicMock(typeof (M));
T t = new T();
mMock.Expect("add_E");
t.Foo((M)mMock.MockInstance);
mMock.Verify();
mMock.Expect("remove_E");
t.Bar((M)mMock.MockInstance);
mMock.Verify();
}
第二步,测试T对M.E事件的处理方法H的内容。办法很简单,把H声明为public即可。
有更直接的办法吗?
答案是StrongTyped Mock
方法是从DynamicMock派生,下面的代码是一种参考实现:
1
class MMock : DynamicMock
2
{
3
private EEventHandler handler;
4
public MMock() : base(typeof (M)) {}
5
6
public void RaiseE()
7
{
8
if (null == handler) Assert.Fail("E is not handled");
9
handler();
10
}
11![]()
12
public void AssertEIsNull()
13
{
14
if (null != handler) Assert.Fail("E is not null");
15
}
16
17
public override Call (string methodName, params object[] args)
18
{
19
case "add_E":
20
handler += (EEventHandler)args[0];
21
return null;
22
case "remove_E":
23
handler -= (EEventHandler)args[0];
24
return null;
25
default:
26
return base.Call(methodName, args);
27
}
28
}
29![]()
class MMock : DynamicMock2
{3
private EEventHandler handler;4
public MMock() : base(typeof (M)) {}5
6
public void RaiseE()7
{8
if (null == handler) Assert.Fail("E is not handled");9
handler();10
}11

12
public void AssertEIsNull()13
{14
if (null != handler) Assert.Fail("E is not null");15
}16
17
public override Call (string methodName, params object[] args)18
{19
case "add_E":20
handler += (EEventHandler)args[0];21
return null;22
case "remove_E":23
handler -= (EEventHandler)args[0];24
return null;25
default:26
return base.Call(methodName, args);27
}28
}29

于是,测试方法中可以这样写:
1
[Test] public void TestEHandler()
2
{
3
MMock mMock = new MMock();
4
T t = new T();
5![]()
6
t.Foo((M)mMock.MockInstance);
7
mMock.RaiseE();
8![]()
9
t.Bar((M)mMock.MockInstance);
10
mMock.AssertEIsNull(false);
11
}
[Test] public void TestEHandler()2
{3
MMock mMock = new MMock();4
T t = new T();5

6
t.Foo((M)mMock.MockInstance);7
mMock.RaiseE();8

9
t.Bar((M)mMock.MockInstance);10
mMock.AssertEIsNull(false);11
}仅供参考



浙公网安备 33010602011771号