微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为 InvokeCommand 中的命令参数编写单元测试

如何解决为 InvokeCommand 中的命令参数编写单元测试

我想编写一个单元测试来检查我的管道,但没有正确的想法。 例如,让我们直接从他们的网站获取管道:

this.WhenAnyValue(x => x.SearchQuery)
    .Throttle(TimeSpan.FromSeconds(0.8),RxApp.TaskpoolScheduler)
    .Select(query => query?.Trim())
    .distinctUntilChanged()
    .Where(query => !string.IsNullOrWhiteSpace(query))
    .ObserveOn(RxApp.MainThreadScheduler)
    .InvokeCommand(ExecuteSearch);

我的想法是在我的单元测试中覆盖 ExecuteSearch 命令并检查提供的参数。但这不起作用,原始命令被执行。

这是我的示例测试装置,我将如何编写测试,但也许我走错了路?

[TestFixture]
public class TestInvokeCommand
{

    [Test]
    public void TestPipeline()
    {
        new TestScheduler().With(scheduler => {
            // implementation of Exampleviewmodel provided below
            var vm = new Exampleviewmodel();
            vm.Activator.Activate();

            var wasExecuted = false;
            // Idea: override 'ExecuteSearch Command' so we have access to
            // the command parameter and write our validation code.
            vm.ExecuteSearch = ReactiveCommand.Create<string>(query => {
                // this is never executed
                Assert.That(query,Is.EqualTo("TestQuery"));
                wasExecuted = true;
            });
            vm.SearchQuery = "TestQuery";
            scheduler.AdvanceByMs(3000);

            Assert.That(wasExecuted,Is.True); // fails here
        });
    }


    // internal class to show how the viewmodel would look like
    class Exampleviewmodel : ReactiveObject,IActivatableviewmodel
    {
        public viewmodelActivator Activator { get; } = new();

        public Exampleviewmodel()
        {
            this.WhenActivated(disposables => {

                ExecuteSearch = ReactiveCommand.CreateFromTask<string>(async (queryString,token) 
                    => await Task.Delay(100,token))
                                 .disposeWith(disposables);

                // directly taken from https://www.reactiveui.net/
                this.WhenAnyValue(x => x.SearchQuery)
                    .Throttle(TimeSpan.FromSeconds(0.8),RxApp.TaskpoolScheduler)
                    .Select(query => query?.Trim())
                    .distinctUntilChanged()
                    .Where(query => !string.IsNullOrWhiteSpace(query))
                    .ObserveOn(RxApp.MainThreadScheduler)
                    .InvokeCommand(ExecuteSearch)
                    .disposeWith(disposables);
            });
        }

        public ReactiveCommandBase<string,System.Reactive.Unit> ExecuteSearch { get; set; }

        private string _searchQuery;
        public string SearchQuery
        {
            get => _searchQuery;
            set => this.RaiseAndSetIfChanged(ref _searchQuery,value);
        }
    }
}

编辑:

感谢下面 Krzysztof 的回答,我发现 ExecuteSearch 的 setter 需要提高 INPT,因为 InvokeCommand 的实现寻找 target.WhenAnyValue(commandProperty)。有了这个改变,它就像一个魅力:)

解决方法

我将管道更改为:

this.WhenAnyValue(x => x.SearchQuery)
    .Throttle(TimeSpan.FromSeconds(0.8),RxApp.TaskpoolScheduler)
    .Select(query => query?.Trim())
    .DistinctUntilChanged()
    .Where(query => !string.IsNullOrWhiteSpace(query))
    .ObserveOn(RxApp.MainThreadScheduler)
    .InvokeCommand(this,x => x.ExecuteSearch);

ExecuteSearch 还需要引发 INotifyPropertyChanged.PropertyChanged 事件。

它将使参考保持最新。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。