c# - ReactiveUI - 在使用 throttle 时测试订阅

标签 c# reactiveui

我在尝试对使用 WhenAnyValue 监听属性更改并根据属性的新值填充列表的 View 模型进行单元测试时遇到问题。由于与第 3 方软件的交互,我需要使用 Throttle 来监听属性的变化。

我的解决方案在生产中有效,但我的单元测试遇到了一些问题。这似乎与没有让测试调度程序正确推进有关,从而真正运行节流后的订阅。我已经创建了我的问题的简化版本,我希望它能说明问题。

查看要测试的模型

public class ViewModel : ReactiveObject
{

    public ViewModel(IScheduler scheduler)
    {
        ListToBeFilled = new List<int>();

        this.WhenAnyValue(vm => vm.SelectedValue)
            .Throttle(TimeSpan.FromMilliseconds(500), scheduler)
            .Skip(1)
            .Subscribe(value =>
            {
                // Do a computation based on value and store result in
                // ListToBeFilled.
                ListToBeFilled = new List<int>() {1, 2, 3};
            });

    }

    private string _selectedValue;
    public string SelectedValue
    {
        get { return _selectedValue; }
        set { this.RaiseAndSetIfChanged(ref _selectedValue, value); }
    }

    public List<int> ListToBeFilled { get; set; } 
}

查看模型测试

[TestFixture]
[RequiresSTA]
public class ViewModelTests
{
    [Test]
    public void TestViewModel()
    {
        // Arrange
        (new TestScheduler()).With(scheduler =>
        {
            ViewModel vm = new ViewModel(scheduler);

            // Act
            vm.SelectedValue = "test value";
            scheduler.AdvanceByMs(1000);

            // Assert
            Assert.AreEqual(3, vm.ListToBeFilled.Count);
        });
    }
}

测试失败说 Expected: 3 But was 0。在不使用 Throttle(我需要它才能在生产中工作)的情况下运行测试时,测试通过。我使用的测试调度程序错了吗?我需要做什么才能消耗掉 Throttle

最佳答案

您的代码(几乎)完全正确,但您被 WhenAnyValue/Sk​​ip 行为欺骗了。

WhenAnyValue 将发布您尝试使用 Skip 跳过的初始值(null)。但是因为 Throttle 正在 TestScheduler 上运行,所以在您有效启动调度程序 (AdvanceBy) 之前不会触发 Skip,此时 2 个更改已排队(null 和 "test value"),但是 Throttle 会丢弃第一个,Skip 第二个,因此您的订阅代码将永远不会被调用。

许多方法可以解决这个问题:

  1. 在设置测试值之前添加 scheduler.AdvanceByMs(1000);(将确保传播初始值)

  2. Skip 移到 Throttle 之前(不需要调度程序,因此会立即应用)

(越晚越好,因为您的代码错误地假设它不会在 View 模型创建后的 500 毫秒内获得选择,这不太可能,但也不是完全不可能)

关于c# - ReactiveUI - 在使用 throttle 时测试订阅,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33215683/

相关文章:

mvvm - 数据注释的确定性评估顺序?

mvvmcross - ReactiveUI 与 MvvmCross

c# - 执行 CompareFileAsync 时输出 "ChecksumNotSupported"FluentFTP

system.reactive - 如何使用 ReactiveUI 和 DynamicData 将可变模型的 ObservableCollection<T> 绑定(bind)到 View 模型的 ReadOnlyObservableCollection<T>

c# - .NET OpenFileDialog 是否可以设置为允许用户选择 .lnk 文件

c# - "Pad Left"在 char 数组上有 0

ios - 如何使用 ReactiveUI 和 DynamicData 链接 SourceList 观察?

c# - 迁移后的 Reactive 6.5.0 ReactiveCommand

c# - 每个线程的处理时间?

c# - 分隔两个 base64 字符串的最佳方法