I'm pretty green with rx/ReactiveUi and want to write a xunit test using TestScheduler to check if the throttle for retrieving search suggestions is working properly.
The idea is to use the TestScheudler for the timing, change the value for the search-term property and check if an async method is called. Unfortunately the method is not called at the expected position (see attached code, especially the unit test).
What am I missing? Is the way I'm trying to test this a good way to go?
My view Model:
public class MyViewModel : ReactiveObject
{
public MyViewModel (IMyQueryHandler queryHandler)
{
...
// Type suggestions
this.SearchTerms = this.ObservableForProperty(x => x.SearchTerm)
.Throttle(SuggestionThrottle).Value();
this.SearchTerms.Subscribe(this.LoadSearchSuggestionsAsync);
...
}
internal async void LoadSearchSuggestionsAsync(string search)
{
...
this.SearchSuggestions = this.queryHandler.ExecuteQuery(...);
...
}
public IList<SearchSuggestion> SearchSuggestions
{
get { return this.searchSuggestions; }
set { this.RaiseAndSetIfChanged(ref this.searchSuggestions, value); }
}
...
}
My Unit Test (xunit):
...
public class TestFixture : ReactiveObject
{
public string SearchTerms { get { return this._searchTermsBackingField.Value; } }
public ObservableAsPropertyHelper<string> _searchTermsBackingField;
}
[Fact]
public void WillTryToLoadSearchSuggestionsAfterThrottleTime()
{
new TestScheduler().With(
sched =>
{
var fixture = new TestFixture();
var queryClient = Substitute.For<IMyQueryHandler>();
var caseSuggestions = new List<...> { ... }
queryClient.ExecuteQuery<...>(...).ReturnsForAnyArgs(...); // Nsubstitute
var vm = new MyViewModel(queryClient);
vm.SearchTerms.ToProperty(fixture, p => p.SearchTerms, out fixture._searchTermsBackingField);
sched.Schedule(() => vm.SearchTerm = "Tes");
sched.Schedule(MyViewModel.SuggestionThrottle, () => vm.SearchTerm = "Test");
sched.AdvanceBy(MyViewModel.SuggestionThrottle.Ticks);
sched.AdvanceBy(1);
// why is the method MyViewModel.LoadSearchSuggestionsAsync not called here (in debug)???
sched.AdvanceBy(1);
} // method gets called here...
}
...