ReactiveUI:为什么我必须在使用TestScheduler时在“... Throttle ...”中明确指定调度程序

时间:2016-02-11 11:59:15

标签: c# unit-testing reactiveui

我是ReactiveUI的新手。我有以下简单的设置:可以指定csv的路径,并向用户显示包含的数据点(使用oxyplot)。 现在我正在尝试测试以下订阅:

public GraphViewModel(IScreen hostScreen)
{
   HostScreen = hostScreen;

   setupGraphFormatting();

   // Data Loading if path is valid
   this.WhenAnyValue(viewModel => viewModel.PathToDataCsv)
      .ObserveOn(RxApp.MainThreadScheduler)
      .Throttle(TimeSpan.FromMilliseconds(500), RxApp.TaskpoolScheduler)
      .Select(csvPath => csvPath?.Trim('"'))
      .Where(csvPath => !string.IsNullOrEmpty(csvPath) && File.Exists(csvPath))
      .Subscribe(csvPath =>
      {
         csvPath = csvPath?.Trim('"');
         updatePlotModel(csvPath);
      }, exception => {});

   /* additional Code*/
}

这就是相应的UnitTest:

[Test]
public void If_PathToDataCsv_has_a_valid_value()
{
   new TestScheduler().With(scheduler =>
   {
      string pathToValidCsvFile = "data.log";
      var viewModel = new GraphViewModel(null);

      scheduler.AdvanceByMs(1000);

      viewModel.PathToDataCsv = pathToValidCsvFile;

      scheduler.AdvanceByMs(1000);

      viewModel.PlotModel.Series.Count.Should().Be(6);
   });
}

我的第一个WhenAnyValue实现没有专门设置任何调度程序(在Throttle中并且没有任何ObserverOn):

public GraphViewModel(IScreen hostScreen)
{
   HostScreen = hostScreen;

   setupGraphFormatting();

   // Data Loading if path is valid
   this.WhenAnyValue(viewModel => viewModel.PathToDataCsv)
      .Throttle(TimeSpan.FromMilliseconds(500))
      .Select(csvPath => csvPath?.Trim('"'))
      .Where(csvPath => !string.IsNullOrEmpty(csvPath) && File.Exists(csvPath))
      .Subscribe(csvPath =>
      {
         csvPath = csvPath?.Trim('"');
         updatePlotModel(csvPath);
      }, exception => {});

   /* additional Code*/
}

然后我的Unittest失败了。我的假设是TestScheduler在幕后用于Throttle,我没有做任何事情。我做错了什么或这是正确的方法:如果我想使用TestScheduler / TimeTravel™,我必须按照我的方式指定调度程序?

编辑以回应Glenn Watsons的回答: 好的,现在很清楚:有问题的方法(Throttle,ObserverOn)当然不使用ReactiveUI的Scheduler,因为这些是Reactive Extensions Framework中的方法。因此,在UnitTest的情况下,ReactiveUI不能隐式替换它们,除非我告诉方法使用RxApp调度程序......

1 个答案:

答案 0 :(得分:2)

RxApp在您处于发布模式时提供ThreadPoolScheduler,在您处于单元测试模式时提供测试调度程序。

默认情况下,响应式扩展(与ReactiveUI分开)将使用自己的默认调度程序,这些调度程序不知道单元测试。