Wpf ReactiveUI:测试单元测试中的可观察属性
RX官方博客上有以下内容: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), //
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,创建一个元组,并在断言表达式中比较这个元组,如第一个示例中所示
好的结果是:
*还是这是一种错误的方法?关于这一点,我看到的唯一一个例子使用了实际的时间度量,如毫秒,但除了油门和类似的方法外,我看不出它们有什么用处。* 所以,因为您不做与时间相关的测试,只做基于顺序的测试(即“我做了这个,然后我做了这个,然后应该是那个”),所以实际上编写一个普通的单元测试要简单得多。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视图模型?或者