尝试对使用 WhenAnyValue 监听属性中的更改的视图模型进行单元测试时出现问题,并根据属性的新值填充列表。由于与第三方软件的交互,我在收听属性的更改时需要使用 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 。在不使用 Throttle (我需要让生产中的东西工作)运行测试时,测试通过。我使用测试调度程序错了吗?为了消耗 Throttle ,我需要做什么?
答案 0 :(得分:4)
您的代码(几乎)完全正确,但您会被WhenAnyValue / Skip行为欺骗。
WhenAnyValue将使用Skip
发布您尝试跳过的初始值(null)。但是因为Throttle
正在TestScheduler上运行,所以在您有效启动调度程序(AdvanceBy
)之前不会命中跳过,此时2个更改排队(null和"test value"
),但Throttle
将删除第一个,Skip
将删除第二个,因此您的订阅代码将永远不会被调用。
解决这个问题的方法很多:
在设置测试值之前添加scheduler.AdvanceByMs(1000);
(将确保传播初始值)
在Skip
之前移动Throttle
(不需要调度程序,因此会立即申请)
(后者可能更好,因为你的代码错误地认为它在创建视图模型后的500ms内不会得到选择,这不太可能,但也不是完全不可能的)