zoukankan      html  css  js  c++  java
  • 艾伟:为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);
            }

         }

    wpfUnitTestError1.png


    为了让调用线程为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);
                  }
    );   

            }

      }



    wpfUnitTestOK.png

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

  • 相关阅读:
    洛谷 P1508 Likecloud-吃、吃、吃
    Codevs 1158 尼克的任务
    2017.10.6 国庆清北 D6T2 同余方程组
    2017.10.6 国庆清北 D6T1 排序
    2017.10.3 国庆清北 D3T3 解迷游戏
    2017.10.3 国庆清北 D3T2 公交车
    2017.10.3 国庆清北 D3T1 括号序列
    2017.10.4 国庆清北 D4T1 财富
    2017.10.7 国庆清北 D7T2 第k大区间
    2017.10.7 国庆清北 D7T1 计数
  • 原文地址:https://www.cnblogs.com/waw/p/2156857.html
Copyright © 2011-2022 走看看