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中的测试代码可以是:
1、作者使用的单元测试工具是NUnit2.4.3,.Net framework 2.0
2、为了说话方便,下文把被测试的类型统称为T,测试类统称为C,被模拟的类型统称为M。
1、测试事件处理方法
考虑下面T的实现
1class 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}
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}
在测试代码中,作者使用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();
}
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派生,下面的代码是一种参考实现:
1class 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
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
于是,测试方法中可以这样写:
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}
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}
仅供参考