ReactiveUI:为什么在使用 TestScheduler 时必须在“...Throttle...”中明确指定调度程序
ReactiveUI: Why do I have to specify the scheduler explicitly in "...Throttle..."when using the TestScheduler
我是 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*/
}
这就是相应的单元测试:
[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*/
}
但是后来我的单元测试失败了。我的假设是 TestScheduler 在幕后被用于 Throttle,我不需要做任何事情。我做错了什么或者这是正确的方法:如果我想使用 TestScheduler/TimeTravel™,我必须像我那样指定调度程序吗?
根据 Glenn Watson 的回答进行编辑:
好的,现在很清楚了:有问题的方法(Throttle、ObserverOn)当然不使用 ReactiveUI 的 Schedulers,因为这些方法来自 Reactive Extensions Framework。因此,在单元测试的情况下,它们不能被 ReactiveUI 隐式替换,除非我告诉方法使用 RxApp 调度程序...
RxApp 在发布模式下提供 ThreadPoolScheduler,在单元测试模式下提供测试调度程序。
默认情况下,响应式扩展(与 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*/
}
这就是相应的单元测试:
[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*/
}
但是后来我的单元测试失败了。我的假设是 TestScheduler 在幕后被用于 Throttle,我不需要做任何事情。我做错了什么或者这是正确的方法:如果我想使用 TestScheduler/TimeTravel™,我必须像我那样指定调度程序吗?
根据 Glenn Watson 的回答进行编辑: 好的,现在很清楚了:有问题的方法(Throttle、ObserverOn)当然不使用 ReactiveUI 的 Schedulers,因为这些方法来自 Reactive Extensions Framework。因此,在单元测试的情况下,它们不能被 ReactiveUI 隐式替换,除非我告诉方法使用 RxApp 调度程序...
RxApp 在发布模式下提供 ThreadPoolScheduler,在单元测试模式下提供测试调度程序。
默认情况下,响应式扩展(与 ReactiveUI 分开)将使用它们自己的默认调度程序,这些调度程序不知道单元测试。