我有一个密码
var i = 0;
_searchService.FindAll()
.SubscribeOn(NewThreadScheduler.Default)
.Subscribe(i => { i++ }, () => { i *= 2; });
据我所知,应用.SubscribeOn(NewThreadScheduler.Default)使IObserver在新线程中运行。一切正常,但我对单元测试有疑问。
我进行了必要的更改,但此订阅运行在另一个框架中不再等待。如何取消.SubscribeOn(NewThreadScheduler.Default)进行单元测试。如果不进行此任命,代码将运行良好。
我已经尝试了反应式UI testScheduler.With(((scheduler)=> {...在此处编写此代码...});但没有成功。我怎么解决这个问题?
最佳答案
您将要使用TestScheduler代替NewThreadScheduler进行单元测试。我假设您使用IoC作为设计模式来启用您的单元测试,因此您所需要做的就是创建一个ISchedulerProvider / ISchedulerService / ...接口,以暴露您的需求。这是我用的东西
public interface ISchedulerProvider
{
/// <summary>
/// Provides access to scheduling onto the UI Dispatcher.
/// </summary>
IScheduler Dispatcher { get; }
/// <summary>
/// Provides concurrent scheduling. Will use the thread pool or the task pool if available.
/// </summary>
IScheduler Concurrent { get; }
/// <summary>
/// Provides concurrent scheduling for starting long running tasks. Will use a new thread or a long running task if available. Can be used to run loops more efficiently than using recursive scheduling.
/// </summary>
ISchedulerLongRunning LongRunning { get; }
/// <summary>
/// Provides support for scheduling periodic tasks. Can be used to run timers more efficiently than using recursive scheduling.
/// </summary>
ISchedulerPeriodic Periodic { get; }
}
public sealed class SchedulerProvider : ISchedulerProvider
{
private readonly IScheduler _dispatcherScheduler;
public SchedulerProvider()
{
var currentDispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher;
_dispatcherScheduler = new DispatcherScheduler(currentDispatcher);
}
public IScheduler Dispatcher
{
get { return _dispatcherScheduler; }
}
public IScheduler Concurrent
{
get { return TaskPoolScheduler.Default; }
}
public ISchedulerLongRunning LongRunning
{
get { return TaskPoolScheduler.Default.AsLongRunning(); }
}
public ISchedulerPeriodic Periodic
{
get { return TaskPoolScheduler.Default.AsPeriodic(); }
}
}
然后,在测试中,您将使用一个返回TestScheduler实现的实现。
public sealed class TestSchedulerProvider : ISchedulerProvider
{
private readonly TestScheduler _dispatcher = new TestScheduler();
private readonly TestScheduler _concurrent = new TestScheduler();
private readonly TestScheduler _longRunning = new TestScheduler();
private readonly TestScheduler _periodic = new TestScheduler();
IScheduler ISchedulerProvider.Dispatcher
{
get { return _dispatcher; }
}
public TestScheduler Dispatcher
{
get { return _dispatcher; }
}
IScheduler ISchedulerProvider.Concurrent
{
get { return _concurrent; }
}
public TestScheduler Concurrent
{
get { return _concurrent; }
}
ISchedulerLongRunning ISchedulerProvider.LongRunning
{
get { return _longRunning.AsLongRunning(); }
}
public TestScheduler LongRunning
{
get { return _longRunning; }
}
ISchedulerPeriodic ISchedulerProvider.Periodic
{
get { return _periodic.AsPeriodic(); }
}
public TestScheduler Periodic
{
get { return _periodic; }
}
}
如您所见,这是针对WPF项目的,但是您可以根据需要进行更改(删除或添加)。
我尝试在我的网站http://introtorx.com/Content/v1.0.10621.0/16_TestingRx.html上详细解释如何使用TestScheduler测试Rx
我不太了解您的示例代码在做什么,但我认为您可能想将其更新为
var testScheduler = new TestScheduler();
var i = 0;
var subscription = _searchService
.FindAll()
.SubscribeOn(testScheduler)
.Subscribe(
i =>i++,
() => i*=2);
Assert.AreEqual(0, i);
testScheduler.AdvanceBy(1);
Assert.AreEqual(1, i);
subscription.Dispose();