测试 DelegateCommand async 无需创建处理程序 public

Test DelegateCommand async without needing to make handler public

Prism 中使用 DelegateCommand 不再可能等待命令执行,因为 FromAsyncHanlder 已从版本 6.3

对于单元测试,建议按如下方式移植,因此如果您有

Task MyHandler() {...}
DelegateCommand myCommand = DelegateCommand.FromAsyncHandler(MyHandler);
/// in test:
await myCommand.Execute();

改为

DelegateCommand myCommand = new DelegateCommand(async () => await MyHandler());
/// in test:
await MyHandler();

然而,这需要创建命令处理程序 (MyHandler) public,这会抵消使用命令模式的封装优势。

我知道我可以 use/create 其他命令实现,但我喜欢 DelegateCommand,因为它是 Prism 的一部分并定期维护。

是否有使用 DelegateCommand 测试异步命令的更好方法?

Is there a better way of testing async commands using the DelegateCommand?

不是真的。由于 DelegateCommand class 没有公开任何异步和可等待的方法,恐怕你不能等待命令本身。

您可以创建 MyHandler() 方法 internal 并将 InternalsVisibleToAttribute 应用于您的程序集:

[assembly: InternalsVisibleTo("UnitTests")] 

也许这样好一点。您的其他选择基本上是制作方法 public 或使用另一个支持 async/await.

ICommand 实现

您对以下方法有何看法:

public class AsyncDelegateCommand : DelegateCommand
{
    private Func<Task> executeAction;

    public AsyncDelegateCommand(Func<Task> executeAction) : base(async () => { await executeAction(); })
    {
        this.executeAction =  executeAction;
    }

    public async Task ExecuteAsync()
    {
        if (CanExecute())
        {
            try
            {
                IsActive = true;
                await executeAction();
            }
            finally
            {
                IsActive = false;
            }
        }

        RaiseCanExecuteChanged();
    }
}

并且可以像这样进行测试:

await myCommand.ExecuteAsync();