单元测试附加行为 wpf

发布于 2024-08-22 08:40:54 字数 2396 浏览 10 评论 0原文

一般来说,我仍在摸索附加行为,并且不知道如何为其编写单元测试。

下面我粘贴了 Sacha Barber 的 Cinch 框架中的一些代码,该框架允许通过附加行为关闭窗口。有人可以给我展示一个示例单元测试吗?

谢谢!
贝里尔

    #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

I am still grokking attached behaviors in general, and am at a loss to see how to write a unit test for one.

I pasted some code below from Sacha Barber's Cinch framework that allows a window to be closed via attached behavior. Can somewone show me an example unit test for it?

Thanks!
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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

朦胧时间 2024-08-29 08:40:54

您可能会在使用 DelegateCommandRelayCommandICommand 中使用 lambda。这些的多种实现随处可见,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 等。

You would likely use a lambda in your ICommand using a DelegateCommand or a RelayCommand. Multiple implementations of these exists all over the place and Cinch may have something similar. Really simple version (as an example, not meant for production use):

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
}

Then your test body might look something like this:

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 );

This is an over-simplified example. There are of course other tests you'll want to perform, in which case you should create or find a fuller implementation of DelegateCommand that also properly implements CanExecute, among other things.

挽心 2024-08-29 08:40:54

对我来说,依赖属性的改变和值强制本身看起来就像“不可能的依赖”。参考 Window 会使事情变得更加棘手。我想我会在这里使用 谦逊对象模式...

DependencyProperty changing and value coercion on their own looks like 'Impossible Dependencies' for me. Having reference to Window there makes things even trickier. I think I'd go with Humble Object pattern here...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文