ReactiveUI:测试单元测试中的可观察属性

时间:2013-01-23 18:15:25

标签: wpf mvvm reactiveui

官方RX博客上有example

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]
);

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

以下是我的VM的代码:

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 =整个列表]
  4. * 或者这是接近它的错误方法吗?我看到的唯一一个例子是使用实际时间测量,例如毫秒,但我不知道它们是如何有用的,除了Throttle和类似的方法。 *

1 个答案:

答案 0 :(得分:3)

所以,因为你没有做与时间相关的测试,只有基于 order 的测试(即“我做了这个,然后我做了这个,那应该是那个),实际上只是编写一个正常的单元测试就简单得多了.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

但是,如果加载RepoList是异步的并且可能需要一些时间,并且您想要表示“正在加载”状态,那么TestScheduler会对此有好处 - 您可以单击复选框说+ 20ms,AdvanceTo(200ms) ,检查您是否处于加载状态,AdvanceTo(10分钟),然后看到列表已更新且状态未加载