我正在重写一个我为了利用ReactiveUI写的WPF-App,以获得关于该库的感觉。推荐测试调度程序/调节程序的方法
我真的很喜欢它!
现在我偶然发现了Throttle
方法,并希望在将过滤器应用到集合时使用它。
这是我的ViewModel:
namespace ReactiveUIThrottle
{
public class MainViewModel : ReactiveObject
{
private string _filter;
public string Filter { get => _filter; set => this.RaiseAndSetIfChanged(ref _filter, value); }
private readonly ReactiveList<Person> _persons = new ReactiveList<Person>();
private readonly ObservableAsPropertyHelper<IReactiveDerivedList<Person>> _filteredPersons;
public IReactiveDerivedList<Person> Persons => _filteredPersons.Value;
public MainViewModel()
{
Filter = string.Empty;
_persons.AddRange(new[]
{
new Person("Peter"),
new Person("Jane"),
new Person("Jon"),
new Person("Marc"),
new Person("Heinz")
});
var filterPersonsCommand = ReactiveCommand.CreateFromTask<string, IReactiveDerivedList<Person>>(FilterPersons);
this.WhenAnyValue(x => x.Filter)
// to see the problem
.Throttle(TimeSpan.FromMilliseconds(2000), RxApp.MainThreadScheduler)
.InvokeCommand(filterPersonsCommand);
_filteredPersons = filterPersonsCommand.ToProperty(this, vm => vm.Persons, _persons.CreateDerivedCollection(p => p));
}
private async Task<IReactiveDerivedList<Person>> FilterPersons(string filter)
{
await Task.Delay(500); // Lets say this takes some time
return _persons.CreateDerivedCollection(p => p, p => p.Name.Contains(filter));
}
}
}
本身就像一个魅力的过滤,也节流,使用GUI时。
不过,我想单元测试过滤的行为,这是我第一次尝试:
[Test]
public void FilterPersonsByName()
{
var sut = new MainViewModel();
sut.Persons.Should().HaveCount(5);
sut.Filter = "J";
sut.Persons.Should().HaveCount(2);
}
这个测试失败,因为集合仍然有5人。
当我摆脱await Task.Delay(500)
在FilterPersons
然后测试会通过,但需要2秒(从油门)。
1)有没有一种方法可以在测试中使油门瞬间加速单元测试?
2)如何测试我的过滤器中的异步行为?
我使用ReactiveUI 7.x的
谢谢您的回复。作为生产代码运行时,你会注入什么模型? 'RxApp.MainThreadScheduler'? 。 –
更新: [测试] 公共无效FilterPersonsByName() { 新TestScheduler()同(SCHED => { 变种SUT =新MainViewModel(附表); SCHED。AdvanceByMs(3000); sut.Persons.Should()。HaveCount(5); sut.Filter =“J”; sched.AdvanceByMs(3000); sut.Persons.Should()。HaveCount(2); }); } 的作品。所以第二点是workign :-)如果我给它'CurrentThreadScheduler.Instace'它仍然运行2-3秒,而不是即时 –
如果你愿意,你当然可以在运行时使用'RxApp'调度器。就我个人而言,我自己创建调度程序并注入它们,但这是个人偏好,而不是必要性。 –