my nunit tips

背景说明:
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}

在测试代码中,作者使用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派生,下面的代码是一种参考实现:

 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

 

于是,测试方法中可以这样写:

 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}

仅供参考

posted on 2007-11-19 21:46  omnislash  阅读(368)  评论(0编辑  收藏  举报