public async Task Test_AsyncRelayCommand_WithCancellation() { TaskCompletionSource <object> tcs = new TaskCompletionSource <object>(); var command = new AsyncRelayCommand(token => tcs.Task); Assert.IsTrue(command.CanExecute(null)); Assert.IsTrue(command.CanExecute(new object())); Assert.IsTrue(command.CanBeCanceled); Assert.IsFalse(command.IsCancellationRequested); command.Execute(null); Assert.IsFalse(command.IsCancellationRequested); command.Cancel(); Assert.IsTrue(command.IsCancellationRequested); tcs.SetResult(null); await command.ExecutionTask !; Assert.IsTrue(command.IsCancellationRequested); }
public async Task Test_AsyncRelayCommand_WithCancellation() { TaskCompletionSource <object> tcs = new TaskCompletionSource <object>(); // We need to test the cancellation support here, so we use the overload with an input // parameter, which is a cancellation token. The token is the one that is internally managed // by the AsyncRelayCommand instance, and canceled when using IAsyncRelayCommand.Cancel(). var command = new AsyncRelayCommand(token => tcs.Task); List <PropertyChangedEventArgs> args = new List <PropertyChangedEventArgs>(); command.PropertyChanged += (s, e) => args.Add(e); // We have no canExecute parameter, so the command can always be invoked Assert.IsTrue(command.CanExecute(null)); Assert.IsTrue(command.CanExecute(new object())); // The command isn't running, so it can't be canceled yet Assert.IsFalse(command.CanBeCanceled); Assert.IsFalse(command.IsCancellationRequested); // Start the command, which will return the token from our task completion source. // We can use that to easily keep the command running while we do our tests, and then // stop the processing by completing the source when we need (see below). command.Execute(null); // The command is running, so it can be canceled, as we used the token overload Assert.IsTrue(command.CanBeCanceled); Assert.IsFalse(command.IsCancellationRequested); // Validate the various event args for all the properties that were updated when executing the command Assert.AreEqual(args.Count, 4); Assert.AreEqual(args[0].PropertyName, nameof(IAsyncRelayCommand.IsCancellationRequested)); Assert.AreEqual(args[1].PropertyName, nameof(IAsyncRelayCommand.ExecutionTask)); Assert.AreEqual(args[2].PropertyName, nameof(IAsyncRelayCommand.IsRunning)); Assert.AreEqual(args[3].PropertyName, nameof(IAsyncRelayCommand.CanBeCanceled)); command.Cancel(); // Verify that these two properties raised notifications correctly when canceling the command too. // We need to ensure all command properties support notifications so that users can bind to them. Assert.AreEqual(args.Count, 6); Assert.AreEqual(args[4].PropertyName, nameof(IAsyncRelayCommand.IsCancellationRequested)); Assert.AreEqual(args[5].PropertyName, nameof(IAsyncRelayCommand.CanBeCanceled)); Assert.IsTrue(command.IsCancellationRequested); // Complete the source, which will mark the command as completed too (as it returned the same task) tcs.SetResult(null); await command.ExecutionTask !; // Verify that the command can no longer be canceled, and that the cancellation is // instead still true, as that's reset when executing a command and not on completion. Assert.IsFalse(command.CanBeCanceled); Assert.IsTrue(command.IsCancellationRequested); }