2010-02-19 40 views
7

我仍然在尋找附加的行爲,並且不知道如何爲其中的單元測試編寫代碼。單元測試一個附加的行爲wpf

我從Sacha Barber的Cinch框架下面粘貼了一些代碼,允許通過附加行爲來關閉窗口。有人可以向我展示一個示例單元測試嗎?

謝謝!
Berryl

#region Close 

    /// <summary>Dependency property which holds the ICommand for the Close event</summary> 
    public static readonly DependencyProperty CloseProperty = 
     DependencyProperty.RegisterAttached("Close", 
      typeof(ICommand), typeof(Lifetime), 
       new UIPropertyMetadata(null, OnCloseEventInfoChanged)); 

    /// <summary>Attached Property getter to retrieve the CloseProperty ICommand</summary> 
    public static ICommand GetClose(DependencyObject source) 
    { 
     return (ICommand)source.GetValue(CloseProperty); 
    } 

    /// <summary>Attached Property setter to change the CloseProperty ICommand</summary> 
    public static void SetClose(DependencyObject source, ICommand command) 
    { 
     source.SetValue(CloseProperty, command); 
    } 

    /// <summary>This is the property changed handler for the Close property.</summary> 
    private static void OnCloseEventInfoChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
    { 
     var win = sender as Window; 
     if (win == null) return; 

     win.Closing -= OnWindowClosing; 
     win.Closed -= OnWindowClosed; 

     if (e.NewValue == null) return; 

     win.Closing += OnWindowClosing; 
     win.Closed += OnWindowClosed; 
    } 

    /// <summary> 
    /// This method is invoked when the Window.Closing event is raised. 
    /// It checks with the ICommand.CanExecute handler 
    /// and cancels the event if the handler returns false. 
    /// </summary> 
    private static void OnWindowClosing(object sender, CancelEventArgs e) 
    { 
     var dpo = (DependencyObject)sender; 
     var ic = GetClose(dpo); 
     if (ic == null) return; 

     e.Cancel = !ic.CanExecute(GetCommandParameter(dpo)); 
    } 

    /// <summary> 
    /// This method is invoked when the Window.Closed event is raised. 
    /// It executes the ICommand.Execute handler. 
    /// </summary> 
    static void OnWindowClosed(object sender, EventArgs e) 
    { 
     var dpo = (DependencyObject)sender; 
     var ic = GetClose(dpo); 
     if (ic == null) return; 

     ic.Execute(GetCommandParameter(dpo)); 
    } 

    #endregion 

回答

5

您可能會在您的ICommand中使用一個lambda,使用DelegateCommandRelayCommand。這些存在的多個實現遍佈整個地方,而且Cinch可能有類似的東西。非常簡單的版本(作爲一個例子,並不是爲生產使用):

public class DelegateCommand : ICommand { 
    private Action _execute = null; 

    public void Execute(object parameter) { 
     _execute(); 
    } 

    public DelegateCommand(Action execute) { 
     _execute = execute; 
    } 

    #region stuff that doesn't affect functionality 
    public bool CanExecute(object parameter) { 
     return true; 
    } 
    public event EventHandler CanExecuteChanged { 
     add { } 
     remove { } 
    } 
    #endregion 
} 

然後測試的身體可能是這個樣子:

bool wascalled = false; 

var execute = new DelegateCommand(
    () => { 
     wascalled = true; 
    }); 

var window = new Window(); 
SomeClass.SetClose(window, execute); 

// does the window need to be shown for Close() to work? Nope. 

window.Close(); 

AssertIsTrue(wascalled); 

這是一個過於簡單化的例子。當然還有其他測試需要執行,在這種情況下,您應該創建或找到更全面的實現DelegateCommand,其中還包括適當實現CanExecute等。

+0

cinch更進一步與繼電器命令通過烘烤你被稱爲測試成CommandSucceeded布爾屬性。您的文章有助於強制執行SetClose在一天結束時仍然是屬性設置器,即使它看起來不像更簡單的普通C#屬性設置器!這是我沒有看到的事情之一,對於我而言對DP /附加行爲並不直觀。歡呼 – Berryl

+0

是的。編譯時,這些靜態的Get/Set方法被調用。與DP一樣:它跳過屬性包裝並直接在'DependencyObject'上調用'SetValue' /'GetValue'。很高興在Cinch聽到這個消息。這不是我已經讀過的。 –

3

DependencyProperty的變化,對自己的長相像我「不可能依賴」價值脅迫。參考Window之後,事情變得更加棘手。我想我會在這裏用Humble Object pattern ...

+0

在這種情況下,我實際上可以住在窗口中,但這是一個有趣的鏈接。你能說明在這種情況下你將如何應用Humble Object Pattern嗎?乾杯 – Berryl