ObservableAsPropertyHelper - do I need to access a value to subscribe to it?

I recently upgraded my ReactiveUI self-packing packages from the latest versions to version (v5.99.4-beta). Some time has passed since I did the update, but many of my tests in ViewModel failed.

The debugger seemed to indicate that my regular Rx sequences were not signed. For instance:

_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 test code looked something like this (short for short):

  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 found the following for the value property for the ObservableAsPropertyHelper object:

  public T Value { get { _inner = _inner ?? _source.Connect(); return _lastValue; } } 

The key line has "_source.Connect ()" - in short, the sequence is not signed until someone reaches the value. In my tests, if I put "vm.Title" before running any rx sequences, everything works fine.

This is an amazing behavior (at least for me), in the sense that the ObservableAsPropertyHelper.Value property must be available before it captures any values. Is this expected behavior? Was this done for efficiency (e.g. lazy instance)? If so, what is the correct way to do this in tests?

Or am I really mistaken in how this works ?:-)

+1
source share
1 answer

Is this the expected behavior?

Yes, this is new for ReactiveUI 6.0.

Was this done to justify effectiveness (for example, a lazy instance)?

That's right - in fact, it can save a lot of memory and work! (15-20% of the memory, as I recall in GitHub for Windows with early tests)

This is an interesting scenario, though - I suspect that in the unit test runner we should subscribe to a design similar to what RxUI 5.x did.

Edit: I would write it like this:

 _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, ""); 

Now you can write your test path easier without TestScheduler:

 var vm = new AddCDSPaperViewModel(obj, parser); var result = await vm.ExecuteSearch.ExecuteAsync("Some String"); Assert.AreEqual("title", result.Title); 
+1
source

Source: https://habr.com/ru/post/974609/


All Articles