您的位置:首页 > 其它

为WPF项目创建单元测试 (zz)

2008-05-04 23:21 465 查看
zz from /article/4664922.html

为WPF项目创建单元测试
周银辉

可能你已发现一个问题,我们无法使用VS对WPF项目创建单元测试(VS2005不行,VS2008我没试过,但据说也不行),这让人很郁闷,这里将介绍如何使用NUnit来对WPF项目创建单元测试并解决其中的难题(但利用NUnit来对WPF创建单元测试时并不会像针对.Net2.0一样容易,可能会出现一些小问题).

1,对普通类(非WPF UI组件)进行测试:
这和在.Net2.0中使用NUnit进行测试时一样,不会出现任何问题,参考下面的代码:


[TestFixture]


public class ClassTest






{


[Test]


public void TestRun()






{


ClassLibrary1.Class1 obj = new ClassLibrary1.Class1();




double expected = 9;


double result = obj.GetSomeValue(3);




Assert.AreEqual(expected, result);


}


}



2,对WPF UI组件进行测试
使用NUnit对WPF UI组件(比如MyWindow,MyUserControl)进行测试的时候,NUnit会报如下异常:“The calling thread must be STA, because many UI components require this”。
下面是错误的测试代码:


[TestFixture]


public class ClassTest






{


[Test]


public void TestRun()






{


WindowsApplication1.Window1 obj = new WindowsApplication1.Window1();




double expected = 9;


double result = obj.GetSomeValue(3);




Assert.AreEqual(expected, result);


}


}





为了让调用线程为STA,我们可以编写一个辅助类CrossThreadTestRunner:


using System;


using System.Collections.Generic;


using System.Text;


using System.Threading;


using System.Security.Permissions;


using System.Reflection;




namespace TestUnit






{


public class CrossThreadTestRunner






{


private Exception lastException;




public void RunInMTA(ThreadStart userDelegate)






{


Run(userDelegate, ApartmentState.MTA);


}




public void RunInSTA(ThreadStart userDelegate)






{


Run(userDelegate, ApartmentState.STA);


}




private void Run(ThreadStart userDelegate, ApartmentState apartmentState)






{


lastException = null;




Thread thread = new Thread(


delegate()






{


try






{


userDelegate.Invoke();


}


catch (Exception e)






{


lastException = e;


}


});


thread.SetApartmentState(apartmentState);




thread.Start();


thread.Join();




if (ExceptionWasThrown())


ThrowExceptionPreservingStack(lastException);


}




private bool ExceptionWasThrown()






{


return lastException != null;


}




[ReflectionPermission(SecurityAction.Demand)]


private static void ThrowExceptionPreservingStack(Exception exception)






{


FieldInfo remoteStackTraceString = typeof(Exception).GetField(


"_remoteStackTraceString",


BindingFlags.Instance | BindingFlags.NonPublic);


remoteStackTraceString.SetValue(exception, exception.StackTrace + Environment.NewLine);


throw exception;


}


}


}



并编写正确的测试代码:


[TestFixture]


public class ClassTest






{


[Test]


public void TestRun()






{




CrossThreadTestRunner runner = new CrossThreadTestRunner();


runner.RunInSTA(


delegate






{


Console.WriteLine(Thread.CurrentThread.GetApartmentState());




WindowsApplication1.Window1 obj = new WindowsApplication1.Window1();




double expected = 9;


double result = obj.GetSomeValue(3);


Assert.AreEqual(expected, result);


});




}


}









另外,使用NUnit时,您需要添加对nunit.framework.dll的引用,并对测试类添加[TestFixture]属性标记以及对测试方法添加[Test]属性标记,然后将生成的程序集用nunit.exe打开就可以了,关于NUnit的具体用法您可以参考其官方文档

DEMO NUnit
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: