2009-04-17 174 views
3

我一直在用我的Silverlight代碼編寫NUnit和Moq一段時間的單元測試。我一直遇到的一個問題與DependencyObjects有關。在Silverlight單元測試中處理DependencyObjects

如果有任何東西是從DependencyObject派生的,那麼我不能在我的測試中實例化它。例如,MouseEventArgs派生自DependencyObject。如果我的代碼使用了這些參數,我不能創建參數有幾個原因......其中之一就是它是一個DependencyObject。

據我所知,DependencyObject的基本構造函數正試圖使用​​一些不存在的靜態,除非整個Silverlight系統啓動並運行。任何派生自DependencyObject的類的構造都會引發異常。遊民。

我不使用Silverlight Unit Test Framework,因爲它實際上不是單元測試,需要一個UI。我運行需要真正的無頭單元測試。

總而言之,我所想到的最好的方法是包裝這些對象併爲它們提供像ITimelineMarker這樣的接口,並且我給它們擴展方法來實現它:timelineMarker.ToInterface()。這很好,我可以嘲笑他們......但我想知道:

有沒有人想出了一個更好的方法來處理Silverlight的單元測試DepencencyObjects?

+0

「派生自DependencyObject的任何類的構造拋出異常」 - 什麼是異常類和錯誤消息? – 2009-05-08 12:22:04

回答

3

爲什麼你的應用程序邏輯直接與SilverLight事件和對象綁定?試圖通過UI來測試應用程序邏輯的警告是衆所周知的反模式,並已經讓位於更有效地解決此問題的模式。

您的用戶界面確實應該只關注用戶界面事件並將任何處理傳遞給其他圖層,然後在用戶界面中測試的唯一東西就是圖形響應(例如,當您單擊按鈕時,側面),測試這種交互的唯一好方法就是實際進行點擊。

也許對您的問題更合適的答案是,您需要重構代碼以使用模式(如MVC,MVP或MVVM),以便您可以獨立於UI層測試應用程序邏輯。

0

你看過TestDriven.NETs Silverlight NUnit Project嗎? Link

+0

是的。這就是我們使用的。該問題發生在該設置中。 – 2009-04-23 23:38:01

0

我可以在抽象類中看到DependencyObject。

從犀牛無恥翻錄嘲笑documentation,想象你有一個抽象類:

public abstract class MessageBase { 
    private List<User> _receivers = new List<User>(); 
    public void Send() { 
     //Some setup 
     DetermineReceivers(); 
     SendMessages(); 
    } 
    private void SendMessages() { 
     //Lots of logic 
    } 
    protected abstract void DetermineReceivers(); 
    protected void AddReceiver(Group g) { 
     //Lots of logic <---- Test this 
    } 
} 

,你要測試的指示的一部分。然後,你會創建一個假類,你可以嘲笑:

TestFixture 
public sealed class MessageBaseTester { 
public abstract class MockMessageMocker 
{ 
    public abstract List<Group> RecipientsGroups { get; set; } 
} 
private class MockMessage : MessageBase { 
    private MockMessageMocker _mock; 
    public MockMessage(MockMessageMocker mock) { 
     _mock = mock; 
    } 
    protected override void DetermineReceivers() { 
     if (_mock.RecipientsGroups != null) 
     foreach(Group g in _mock.RecipientsGroups) 
      base.AddReceiver(g); 
    } 
} 
} 

之後你的測試可以做到以下幾點:

Test 
public void ShouldblablablaWhenBlabla() { 
    var SuThelper = mocks.Stub(); 
    var SuT = new MockMessage(SuThelper); 
    using (mocks.Record()) 
    { 
     Expect.Call(SuTHelper.RecipientsGroups).Return(
      new List<Group>{ new Group(...) }); 
    } 
    using (mocks.Playback()) 
    { 
     SuT.Send(); 
    } 
} 

上述解決方案擁有你的優勢,你不需要修改您的原始代碼。然而,你需要編寫一些「額外」的代碼才能工作。

+0

不幸的是,這不起作用。我需要替換的對象是派生自DependencyObject(例如MouseEventArgs),它們通常是密封的,構造函數是內部的:( – 2009-05-05 20:31:17

+0

對不起,但是我沒有看到任何派生自DependencyObject的MSDN中的MouseEventArgs。請您提供一個鏈接? – drozzy 2009-05-05 20:41:13

+0

@drozzy:Doat!你說得對... MouseEventArgs不是從DependencyObject派生出來的,它確實遭受了類似的問題,儘管它是一個帶有內部構造函數的密封類 Some better例子(關閉我的頭頂)是System.Windows.Media.SolidColorBrush或System.Windows.Media.TimelineMarker。 此外,Rhino Mocks是否可以在Silverlight中工作?這只是一個小問題... Moq在SL和可以抽出抽象類,即使我用我從(System.Windows.Media.Brush)派生的類型來嘗試它,我仍然可以得到外部在基礎構造函數中。 – 2009-05-06 11:49:23