0

RX 官方博客上有这个例子:

var scheduler = new TestScheduler();

var xs = scheduler.CreateColdObservable(
    OnNext(10, 42),
    OnCompleted<int>(20)
);

var res = scheduler.Start(() => xs);

res.Messages.AssertEqual(
    OnNext(210, 42),            // Subscribed + 10
    OnCompleted<int>(220)       // Subscribed + 20
);

xs.Subscriptions.AssertEqual(
    Subscribe(200, 1000)        // [Subscribed, Disposed]
);

我想用reactiveui做这样的事情。我的意思是代替 scheduler.CreateColdObservable(...) 使用来自实际属性更改通知的流。问题是我尝试了 vm.ObservableForProperty 和 vm.Changed 但它们的工作不一致(并非所有属性更改都创建了一个事件或值为 null)

这是我的虚拟机的代码:

internal class ProductFileEditorVM : ReactiveObject
{
    private readonly List<string> _preloadedList;

    private bool _OnlyContainingProduct;
    public bool OnlyContainingProduct
    {
        get { return _OnlyContainingProduct; }
        set
        {
            this.RaiseAndSetIfChanged(x => x.OnlyContainingProduct, value);
        }
    }

    private ObservableAsPropertyHelper<IEnumerable<string>> _RepoList;
    public IEnumerable<string> RepoList
    {
        get{return _RepoList.Value;}
    }

    public ProductFileEditorVM(RepositoryManager repositoryManager)
    {

        //Set defaults
        OnlyContainingProduct = true;

        //Preload
        _preloadedList = repositoryManager.GetList();

        var list = this.WhenAny(x => x.OnlyContainingProduct,
                     ocp =>
                     ocp.Value
                         ? _preloadedRepoList.Where(repo => repo.ToLower().Contains("product"))
                         : _preloadedRepoList);
        list.ToProperty(this, x => x.RepoList);
    }
}

理想情况下,我想在这两个属性上使用 Observable.CombineLatest 并创建一个元组并在断言表达式中比较这个元组,就像在第一个示例中一样。

好的结果是:

  1. [OnlyContainingProduct==true;RepoList= 过滤后的]
  2. !将 OnlyContainingProduct 更改为 false
  3. [OnlyContainingProduct==false;RepoList= 整个列表]

*或者这是错误的处理方式?我看到的唯一示例使用了毫秒等实际时间度量,但除了 Throttle 和类似方法外,我看不出它们有什么用处。*

4

1 回答 1

4

所以,因为你没有做与时间相关的测试,只做基于顺序的测试(即“我做了这个,然后我做了这个,然后它应该是那个),实际上只写一个普通的要简单得多单元测试。TestScheduler 是一把大锤 :)

因此,您可以执行以下操作:

var fixture = new ProductFileEditorVM();

bool repoListChanged = false;
fixture.WhenAny(x => x.RepoList, x => x.Value)
    .Subscribe(_ => repoListChanged = true);

fixture.OnlyContainingProduct = true;
Assert.True(repoListChanged);

何时使用 TestScheduler

However, if loading RepoList was asynchronous and could take some time, and you wanted to represent a "Loading" state, a TestScheduler would be good for that - you'd click the checkbox at say +20ms, AdvanceTo(200ms), check to see if you're in Loading state, AdvanceTo(10min), then see that the list is updated and the state isn't Loading

于 2013-01-23T21:09:28.070 回答