Pergunta

Ainda estou gritando comportamentos anexados em geral e estou sem ver como escrever um teste de unidade para um.

Eu colei algum código abaixo da estrutura Cinch de Sacha Barber que permite que uma janela seja fechada por meio de comportamento em anexo. SomeWone pode me mostrar um exemplo de teste de unidade para isso?

Obrigado!
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
Foi útil?

Solução

Você provavelmente usaria um lambda em seu ICommand usando um DelegateCommand ou a RelayCommand. Múltiplas implementações dessas existe em todo o lugar e Cinch pode ter algo semelhante. Versão realmente simples (como exemplo, não destinada ao uso da produção):

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
}

Então seu corpo de teste pode parecer algo assim:

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

Este é um exemplo super simplificado. É claro que existem outros testes que você deseja executar; nesse caso, você deve criar ou encontrar uma implementação mais completa de DelegateCommand que também implementa corretamente CanExecute, entre outras coisas.

Outras dicas

DependencyProperty Mudança e coerção de valor por conta própria parece 'dependências impossíveis' para mim. Ter referência à janela lá torna as coisas ainda mais complicadas. Eu acho que iria com Padrão de objeto humilde aqui...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top