Skip to content

Instantly share code, notes, and snippets.

@JakeGinnivan
Created August 7, 2012 07:30
Show Gist options
  • Save JakeGinnivan/3282830 to your computer and use it in GitHub Desktop.
Save JakeGinnivan/3282830 to your computer and use it in GitHub Desktop.
Testing async commands
//Your code you are testing:
public IAsyncCommand SignInCommand { get; private set; }
public ctor()
{
SignInCommand = new AwaitableDelegateCommand(Login);
}
private async Task Login()
{
//stuff
}
// Your test
public async Task Test()
{
var vmUnderTest = new MyViewModel();
await vmUnderTest.SignInCommand.ExecuteAsync()
Assert.Whatever();
}
public interface IAsyncCommand : IAsyncCommand<object>{}
public interface IAsyncCommand<in T> : ICommand, IRaiseCanExecuteChanged
{
Task ExecuteAsync(T obj);
}
public class AwaitableDelegateCommand : AwaitableDelegateCommand<object>, IAsyncCommand
{
public AwaitableDelegateCommand(Func<object, Task> executeMethod)
: base(executeMethod)
{
}
public AwaitableDelegateCommand(Func<object, Task> executeMethod, Func<object, bool> canExecuteMethod)
: base(executeMethod, canExecuteMethod)
{
}
}
public class AwaitableDelegateCommand<T> : IAsyncCommand<T>
{
private readonly Func<T, Task> _executeMethod;
private readonly DelegateCommand<T> _underlyingCommand;
private bool _isExecuting;
public AwaitableDelegateCommand(Func<T, Task> executeMethod)
: this(executeMethod, _ => true)
{
}
public AwaitableDelegateCommand(Func<T, Task> executeMethod, Func<T, bool> canExecuteMethod)
{
_executeMethod = executeMethod;
_underlyingCommand = new DelegateCommand<T>(x => { }, canExecuteMethod);
}
public async Task ExecuteAsync(T obj)
{
try
{
_isExecuting = true;
RaiseCanExecuteChanged();
await _executeMethod(obj);
}
finally
{
_isExecuting = false;
RaiseCanExecuteChanged();
}
}
public bool CanExecute(object parameter)
{
return !_isExecuting && _underlyingCommand.CanExecute((T)parameter);
}
public event EventHandler CanExecuteChanged
{
add { _underlyingCommand.CanExecuteChanged += value; }
remove { _underlyingCommand.CanExecuteChanged -= value; }
}
public async void Execute(object parameter)
{
await ExecuteAsync((T)parameter);
}
public void RaiseCanExecuteChanged()
{
_underlyingCommand.RaiseCanExecuteChanged();
}
}
public interface IRaiseCanExecuteChanged
{
void RaiseCanExecuteChanged();
}
/// <summary>
/// A command that calls the specified delegate when the command is executed.
/// </summary>
/// <typeparam name="T"></typeparam>
public class DelegateCommand<T> : ICommand, IRaiseCanExecuteChanged
{
private readonly Func<T, bool> _canExecuteMethod;
private readonly Action<T> _executeMethod;
private bool _isExecuting;
public DelegateCommand(Action<T> executeMethod)
: this(executeMethod, null)
{
}
public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
{
if ((executeMethod == null) && (canExecuteMethod == null))
{
throw new ArgumentNullException("executeMethod", @"Execute Method cannot be null");
}
_executeMethod = executeMethod;
_canExecuteMethod = canExecuteMethod;
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
bool ICommand.CanExecute(object parameter)
{
return !_isExecuting && CanExecute((T)parameter);
}
void ICommand.Execute(object parameter)
{
_isExecuting = true;
try
{
RaiseCanExecuteChanged();
Execute((T)parameter);
}
finally
{
_isExecuting = false;
RaiseCanExecuteChanged();
}
}
public bool CanExecute(T parameter)
{
if (_canExecuteMethod == null)
return true;
return _canExecuteMethod(parameter);
}
public void Execute(T parameter)
{
_executeMethod(parameter);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment