2011-06-03 108 views
13

在執行以下兩個測試用例之後,將COM執行打印到控制檯。我究竟做錯了什麼?使用WPF退出時的COM異常

如果我單獨運行任何一個測試,或者如果我一起運行這兩個測試,那麼這個異常就會正好寫入控制檯一次。這讓我懷疑有某種每AppDomain資源,我沒有清理。

我已經嘗試過使用NUnit和MSTest的測試,在兩種環境中都有相同的行爲。 (其實,我不知道,如果在一個異常打印或兩個運行在MSTest的結果這兩個試驗。)

例外:

System.Runtime.InteropServices.InvalidComObjectException: COM object that has been separated from its underlying RCW cannot be used. 
at System.Windows.Input.TextServicesContext.StopTransitoryExtension() 
at System.Windows.Input.TextServicesContext.Uninitialize(Boolean appDomainShutdown) 
at System.Windows.Input.TextServicesContext.TextServicesContextShutDownListener.OnShutDown(Object target) 
at MS.Internal.ShutDownListener.HandleShutDown(Object sender, EventArgs e) 

測試代碼:

using NUnit.Framework; 

namespace TaskdockSidebarTests.Client 
{ 
    [TestFixture, RequiresSTA] 
    public class ElementHostRCWError 
    { 
     [Test] 
     public void WinForms() 
     { 
      var form = new System.Windows.Forms.Form(); 
      var elementHost = new System.Windows.Forms.Integration.ElementHost(); 
      form.Controls.Add(elementHost); 

      // If the form is not shown, the exception is not printed. 
      form.Show(); 

      // These lines are optional. The exception is printed with or without 
      form.Close(); 
      form.Controls.Remove(elementHost); 
      elementHost.Dispose(); 
      form.Dispose(); 
     } 

     [Test] 
     public void WPF() 
     { 
      var window = new Window(); 

      // If the window is not shown, the exception is not printed. 
      window.Show(); 

      window.Close(); 
     } 
    } 
} 
+0

也許http://social.msdn.microsoft.com/forums/en-US/vststest/thread/e53fdc45-23f3-4aee-aad9-f6​​3769f2c638/幫助 – 2011-06-03 22:03:27

+0

可悲的是,我不能使用MTA,因爲WPF需要STA。在SetUp中創建表單和元素主機似乎也無法做到這一點。哎呀。 – 2011-06-03 22:50:04

+0

如果我沒有弄錯,這個異常不會導致unittest失敗,是嗎?在單元測試我的WPF控件時,我遇到了同樣的異常,我選擇忽略它;;) – Bubblewrap 2011-06-04 11:18:10

回答

18

再次查看我自己的代碼,下面一行可能有助於WPF測試,最後。

Dispatcher.CurrentDispatcher.InvokeShutdown(); 
+0

Sweeeeet!那樣做了。謝謝!現在我只需要弄清楚如何將它融入到我的測試架構中。 – 2011-06-05 21:47:55

+0

令人失望的是,一旦調度程序被綁定到一個線程(即Dispatcher.CurrentDispatcher),則不能將其他調度程序與該線程關聯。一旦調度員關閉,它不能重新啓動。所以,雖然這解決了我的問題,但我可惜不能在我的基本測試類的TearDown方法中調用InvokeShutdown()。 – 2011-06-05 23:30:47

+0

嘗試在每個unittest中啓動一個新的STA線程,在該新線程中執行測試,然後等待該線程使用Thread.Join()完成。 – Bubblewrap 2011-06-06 06:01:33

1

你大概可以't單元測試WindowForm類。 WinForms應用程序和WPF應用程序都有一個Application類用於啓動底層管道(消息泵和什麼)。我敢打賭這是避免這種例外的關鍵。

你沒有那樣做,可能無法做到。

我讀過的單元測試的每個建議都是你重構的,以便Form類和Window類不需要進行任何單元測試(如WPF中的M-V-VM模式)。可能與無法顯示用戶界面有關。

還有其他方法可以測試UI。 This answer討論了單元測試UI。

+3

其實,測試運行良好 - 我只是在我的日誌文件中結束了很多垃圾。關於用戶界面測試與直接業務邏輯測試 - 我認爲,我越接近測試用戶處理的實際事物,我越會在晚上睡覺。 – 2011-06-05 21:43:23

+0

喬爾和帕特里克+1,因爲我認爲你是對的。雖然我同意喬爾的設計應該是這樣的 - 你不能說有時你只需要自動化一些控件/窗口,只是因爲一些舊的/脆弱/ notyours代碼需要它。 – quetzalcoatl 2012-03-20 10:04:57