我最近将我的ReactiveUI金块包更新到最新的预发行版本(v5.99.4-beta)。我做了更新已经有一段时间了,但是我对ViewModel的许多测试都失败了。
调试器似乎表明我正常的Rx序列没有被订阅。例如:
_executeSearch = ReactiveCommand.Create();
var paper = _executeSearch
.Where(x => x is string)
.SelectMany(x => _searchParser.GetPaperFinders(x as string))
.SelectMany(x => x.FindPaper());
paper
.Select(x => x.Item1.Title)
.ToProperty(this, x => x.Title, out _TitleOAPH, "");
我的测试代码看起来像这样(为了简洁起见):
INavService obj = Mock...
ISearchStringParser parser = ...
var vm = new AddCDSPaperViewModel(obj, parser);
vm.CDSLookupString = "1234"; // trigger the "search"
... (test scheduler is advanced to wait for search results to show up
Assert.AreEqual("title", vm.Title, "searched for title"); // vm.Title is unset, though it should be!
我查看了github上的reactiveui源代码,并发现了以下ObservableAsPropertyHelper对象的“value”属性:
public T Value {
get {
_inner = _inner ?? _source.Connect();
return _lastValue;
}
}
关键行是“_source.Connect()” - 简而言之,在有人访问Value之前,序列不会被订阅。在我的测试中,如果我在运行任何rx序列之前输入“vm.Title”,那么一切正常。
这是令人惊讶的行为(至少对我来说),因为必须在捕获任何值之前访问ObservableAsPropertyHelper.Value属性。这是预期的行为吗?这是为了提高效率(例如懒惰实例化)的原因吗?如果是这样,在测试中绕过这个的正确方法是什么?
或者我对这是如何工作的错误? : - )
答案 0 :(得分:1)
这是预期的行为吗?
是的,这是ReactiveUI 6.0的新功能。
是否为效率(例如懒惰的实例化)原因而做了?
正确 - 它实际上可以最终节省大量内存和工作! (我在早期的测试中回忆起GitHub for Windows中15-20%的内存)
这是一个有趣的场景 - 我怀疑在单元测试运行中,我们应该订阅构造,类似于RxUI 5.x所做的。
编辑:我会这样写:
_executeSearch = ReactiveCommand.Create(_ => Observable.Return(x)
.Where(x => x is string)
.SelectMany(x => _searchParser.GetPaperFinders(x as string))
.SelectMany(x => x.FindPaper()));
_executeSearch
.Select(x => x.Item1.Title)
.ToProperty(this, x => x.Title, out _TitleOAPH, "");
现在,您可以更轻松地编写测试方式,无需TestScheduler:
var vm = new AddCDSPaperViewModel(obj, parser);
var result = await vm.ExecuteSearch.ExecuteAsync("Some String");
Assert.AreEqual("title", result.Title);