I recently updated my ReactiveUI nugget packages to the latest pre-release versions (v5.99.4-beta). It has been a while since I did the update, but many of my tests on ViewModel's failed.
The debugger seemed to indicate that my normal sequences of Rx weren't getting subscribed to. For example:
_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, "");
And my tests code looked something like this (cut for brevity):
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!
I looked at the reactiveui source code on github and discovered the following for the "value" property on the ObservableAsPropertyHelper object:
public T Value {
get {
_inner = _inner ?? _source.Connect();
return _lastValue;
}
}
The key line there is "_source.Connect()" - in short, the sequence isn't subscribed to until someone access Value. In my tests, if I put a "vm.Title" before I run any rx sequences, then everything works just fine.
This is surprising behavior (at least to me), in the sense that the ObservableAsPropertyHelper.Value property has to be accessed before it will capture any values. Is this expected behavior? Was it done for efficiency (e.g. lazy instantiation) reasons? If so, what is the proper way around this in tests?
Or am I very mistaken in how this works? :-)