C# ReactiveUI-使用油门时测试订阅

C# ReactiveUI-使用油门时测试订阅,c#,reactiveui,C#,Reactiveui,当尝试对使用WhenyValue侦听属性中的更改并基于属性的新值填充列表的视图模型进行单元测试时,我遇到了一个问题。由于与第三方软件的交互,我需要在收听属性更改时使用Throttle 我的解决方案可以在生产中使用,但是我的单元测试遇到了一些问题。这似乎与没有让测试调度器正确地前进有关,因此在节流之后的订阅实际上是运行的。我已经为我的问题创建了一个简化版本,我希望它能说明问题 查看要测试的模型 public class ViewModel : ReactiveObject { publi

当尝试对使用WhenyValue侦听属性中的更改并基于属性的新值填充列表的视图模型进行单元测试时,我遇到了一个问题。由于与第三方软件的交互,我需要在收听属性更改时使用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);
        });
    }
}
测试失败,预期为3,但为0。在不使用节流阀的情况下运行测试时(我需要在生产中使用节流阀),测试通过。我是否使用了错误的测试调度程序?要使用油门,我需要做什么?

您的代码(几乎)完全正确,但您被WhenyValue/Skip行为欺骗了

WhenyValue将发布一个初始值(null),您正试图使用
跳过
。但是,由于TestScheduler上正在运行
Throttle
,因此在有效启动调度程序(
AdvanceBy
)之前,不会点击Skip,此时2个更改将排队(null和
“test value”
),但是
Throttle
将删除第一个,而
Skip
将删除第二个,因此,您的订阅代码将永远不会被调用

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

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

  • 节流阀之前移动
    跳过
    (不需要计划程序,因此将立即应用)

  • (后者可能更好,因为您的代码错误地假设它在视图模型创建后500毫秒内不会得到选择,这是不可能的,但也不是完全不可能的)