Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf ReactiveUI:测试单元测试中的可观察属性_Wpf_Mvvm_Reactiveui - Fatal编程技术网

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

Wpf ReactiveUI:测试单元测试中的可观察属性,wpf,mvvm,reactiveui,Wpf,Mvvm,Reactiveui,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), //

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]
);
var scheduler=newtestscheduler();
var xs=scheduler.CreateColdObservable(
OnNext(10,42),
未完成(20)
);
var res=scheduler.Start(()=>xs);
res.Messages.AssertEqual(
OnNext(210,42),//订阅+10
未完成(220)//订阅+20
);
xs.Subscriptions.AssertEqual(
认购(2001000)/[认购,处置]
);
我想用reactiveui做一些类似的事情。我的意思是使用来自实际属性更改通知的流,而不是scheduler.CreateColdObservable(…)。问题是我尝试了vm.observeForProperty和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);
    }
}
内部类ProductFileEditorVM:ReactiveObject
{
私有只读列表\u预加载列表;
仅包含产品的私有布尔;
仅限公共广播内容的产品
{
获取{return\u only containing product;}
设置
{
this.RaiseAndSetIfChanged(x=>x.OnlyContainingProduct,value);
}
}
私有可观察属性帮助者报告列表;
公共IEnumerable报告列表
{
获取{return\u RepoList.Value;}
}
公共产品FileEditorVM(RepositoryManager RepositoryManager)
{
//设置默认值
仅包含产品=真;
//预载
_preload=repositoryManager.GetList();
var list=this.WhenAny(x=>x.OnlyContainingProduct,
ocp=>
ocp.值
?_preadedrepolist.Where(repo=>repo.ToLower().包含(“产品”))
:_预报告列表);
TopProperty(这个,x=>x.RepoList);
}
}
理想情况下,我希望对这两个属性使用Observable.CombineTest,创建一个元组,并在断言表达式中比较这个元组,如第一个示例中所示

好的结果是:

  • [OnlyContainingProduct==true;RepoList=过滤后的产品]
  • !!将Only Containing Product更改为false
  • [OnlyContainingProduct==false;RepoList=整个列表]

  • *还是这是一种错误的方法?关于这一点,我看到的唯一一个例子使用了实际的时间度量,如毫秒,但除了油门和类似的方法外,我看不出它们有什么用处。*

    所以,因为您不做与时间相关的测试,只做基于顺序的测试(即“我做了这个,然后我做了这个,然后应该是那个”),所以实际上编写一个普通的单元测试要简单得多。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(10min),然后查看列表已更新,并且状态未加载,因此,因为您没有执行与时间相关的测试,只执行基于顺序的测试(即“我做了这个,然后我做了这个,然后应该是那个”),所以只编写一个普通的单元测试实际上要简单得多。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(10min),然后查看列表是否已更新,状态是否未加载

    OK,我更接近理解,但仍然困惑。我怎么知道未来200毫秒仍然是加载状态?如果出于某种原因,它加载速度过快怎么办?我之所以理解10分钟(或其他什么),是因为我可以将超时设置为10分钟。啊,这是我遗漏的部分-您将RepoList的加载方法模拟为CreateColdObservable,它以+200ms的速度返回单个项并完成。由于TestScheduler会立即运行它们,所以这些时间实际上都不重要,它只是对可读性和理解testOK有用,这样我就可以接受答案。从理论上讲,如果有人创建了一个包含多个具有异步行为且相互依赖的控件的ui,该怎么办。这是一个超级复杂的状态机。您是否认为有一种终极模式可以测试任意复杂的rx视图模型?或者,不管复杂程度如何,上面的示例(只是更复杂)总是足够的,只有在有某种实时性的情况下才需要虚拟时间?除非您正在测试涉及时间的东西(即超时/延迟/间隔/窗口),否则您永远不需要TestScheduler,特别是如果您总是确保每个异步方法都经过RxApp.TaskpoolScheduler或RxApp.deferredScheduler,谢谢!对于使用RxApp.TaskpoolScheduler或RxApp.DeferredScheduler测试东西,是否有任何特殊的考虑?好的,我更容易理解,但仍然感到困惑。我怎么知道未来200毫秒仍然是加载状态?如果出于某种原因,它加载速度过快怎么办?我之所以理解10分钟(或其他什么),是因为我可以将超时设置为10分钟。啊,这是我遗漏的部分-您将RepoList的加载方法模拟为CreateColdObservable,它以+200ms的速度返回单个项并完成。由于TestScheduler会立即运行它们,所以这些时间实际上都不重要,它只是对可读性和理解testOK有用,这样我就可以接受答案。从理论上讲,如果有人创建了一个包含多个具有异步行为且相互依赖的控件的ui,该怎么办。这是一个超级复杂的状态机。您是否认为有一种终极模式可以测试任意复杂的rx视图模型?或者