【发布时间】:2015-12-02 23:21:53
【问题描述】:
我在测试 ReactiveCommand 及其执行能力时遇到了问题。
给定以下视图模型:
public class HowToTestViewModel : ReactiveObject
{
public ReactiveCommand<Unit> CommandThatDoesStuff { get; set; }
public IObservable<bool> CanExecute { get; set; }
public ObservableCollection<string> TheCollectionMustHaveItems { get; set; }
public HowToTestViewModel()
{
TheCollectionMustHaveItems = new ObservableCollection<string>();
this.CanExecute = this.WhenAnyValue(vm => vm.TheCollectionMustHaveItems)
.Do(debug => Console.WriteLine("Can Execute Value: " + debug.Count()))
.Where(col => col.Any())
.Do(debug => Console.WriteLine("Can Execute (not empty?) Value: " + debug.Count()))
.Select(x => true);
CommandThatDoesStuff = ReactiveCommand.CreateAsyncTask(this.CanExecute, async param => {
//web service or something...
await Task.Delay(1000);
});
CommandThatDoesStuff.Subscribe(next => Console.WriteLine("The command fired and no exceptions were thrown."));
CommandThatDoesStuff.ThrownExceptions.Subscribe(error => Console.WriteLine("boom. handle your business here."));
}
}
我想测试确保命令不能被执行,除非TheCollectionMustHaveItems不为空并且有项目。
[Test]
public void CanExecute_spec()
{
(new TestScheduler()).With(sched =>
{
var sut = new HowToTestViewModel();
sut.CommandThatDoesStuff.Execute(null);
sut.CommandThatDoesStuff.CanExecute(null).Should().BeFalse();
sut.TheCollectionMustHaveItems.Should().BeEmpty();
sut.TheCollectionMustHaveItems.Add("item added"); //CanExecute should update
sched.AdvanceBy(1000);
sut.CommandThatDoesStuff.CanExecute(null).Should().BeTrue();
});
}
我正在使用TestScheduler,但我不知道为什么。我的问题是:
- 如何让测试通过?
- 我应该在命令上测试 CanExecute 吗?
- 我应该使用 ToPropery 和 ObservableAsPropertyHelper 而不是 CanExecute 的公共 IObservable?
更新 1
按照下面的建议,我将 ObservableCollection 更改为 ReactiveList 并且我(认为)我正在使用 TheCollectionMustHaveItems.CountChanged 来验证 CommandThatDoesStuff 是否可以执行。使用以下更新的虚拟机和测试我得到了同样的错误。
public class HowToTestViewModel : ReactiveObject
{
....
public IReactiveList<string> TheCollectionMustHaveItems { get; set; }
public HowToTestViewModel()
{
TheCollectionMustHaveItems = new ReactiveList<string>();
this.CanExecute = this
.TheCollectionMustHaveItems.CountChanged
.Do(next => Console.WriteLine("logging the next result:" + next))
.ObserveOn(RxApp.MainThreadScheduler)
.Where(collection => TheCollectionMustHaveItems.Any())
.Select(x => true);
...
}
}
更新 2
将测试更新到await CommandThatDoesStuff 会导致测试运行程序永远不会返回。
[Test]
public async void CanExecute_spec()
{
await (new TestScheduler()).With(async sched =>
{
var sut = new HowToTestViewModel();
await sut.CommandThatDoesStuff.ExecuteAsyncTask(null);
sut.CommandThatDoesStuff.CanExecute(null).Should().BeFalse();
sut.TheCollectionMustHaveItems.Should().BeEmpty();
sut.TheCollectionMustHaveItems.Add("item added"); //CanExecute should update
sut.CanExecute.Subscribe(next => next.Should().BeTrue());
sched.AdvanceBy(1000);
sut.CommandThatDoesStuff.CanExecuteObservable.Subscribe(next => next.Should().BeTrue());
});
}
【问题讨论】:
标签: c# observablecollection system.reactive reactive-programming reactiveui