测试和调试可观察序列

来源:互联网 发布:怎样委托网络投资理财 编辑:程序博客网 时间:2024/05/22 03:27

  如果你有一个可观察的序列在一个延长的时间内发布值,实时测试可以是一个伸展。 Reactive Extension库提供TestScheduler类型,以帮助测试这种时间依赖代码,而不需要等待时间通过。 TestScheduler继承VirtualScheduler并允许您在仿真时间创建,发布和订阅序列。例如,您可以压缩出版物,需要5天才能完成到2分钟运行,同时保持正确的比例。您还可以采用实际上在过去发生的序列(例如,前一年的股票行情序列),并计算或订阅该序列,就像实时推出新值一样。
工厂方法Start执行所有计划任务,直到队列为空,或者您可以指定一个时间,以便排队的任务只执行到指定的时间。
  以下示例使用指定的OnNext通知创建热可观察序列。然后它启动测试调度程序,并指定何时订阅和处理热可观察序列。 Start方法返回ITestableObserver的实例,它包含一个记录列表中所有通知的Messages属性。
  在序列完成之后,我们使用ReactiveAssert.AreElementEqual方法来比较Messages属性以及期望值的列表,以查看两者是否相同(具有相同数量的项目,项目相等且顺序相同) 。通过这样做,我们可以确认我们确实收到了我们期望的通知。在我们的例子中,由于我们只开始在150订阅,我们将错过abc值。然而,当我们比较到目前为止在400处的值时,我们注意到,在我们订阅序列之后,我们实际上已经收到了所有公布的值。我们还验证OnCompleted通知在正确的时间在500处触发。此外,订阅信息也由CreateHotObservable方法返回的ITestableObservable类型捕获。
  以同样的方式,您可以使用ReactiveAssert.AreElementsEqual来确认订阅确实发生在预期的时间。

using System;using System.Reactive;using System.Reactive.Linq;using Microsoft.Reactive.Testing;class Program : ReactiveTest{    static void Main(string[] args)    {        var scheduler = new TestScheduler();        var input = scheduler.CreateHotObservable(            OnNext(100, "abc"),            OnNext(200, "def"),            OnNext(250, "ghi"),            OnNext(300, "pqr"),            OnNext(450, "xyz"),            OnCompleted<string>(500)            );        var results = scheduler.Start(            () => input.Buffer(() => input.Throttle(TimeSpan.FromTicks(100), scheduler))                       .Select(b => string.Join(",", b)),            created: 50,            subscribed: 150,            disposed: 600);        ReactiveAssert.AreElementsEqual(results.Messages, new Recorded<Notification<string>>[] {                OnNext(400, "def,ghi,pqr"),                OnNext(500, "xyz"),                OnCompleted<string>(500)            });        ReactiveAssert.AreElementsEqual(input.Subscriptions, new Subscription[] {                Subscribe(150, 500),                Subscribe(150, 400),                Subscribe(400, 500)            });    }}

调试Rx应用程序

  您可以使用Do操作符调试Rx应用程序。 Do操作符允许您指定为可观察序列的每个项目采取的各种动作(例如,打印或记录项目等)。这在您链接许多运算符并且想要知道在每个级别生成什么值时尤其有用。
  在下面的例子中,我们将重用Buffer示例,每秒生成一个整数,同时将它们放入可以容纳5个项目的缓冲区中。在我们使用LINQ运算符的查询可观察序列的原始示例中,当缓冲区已满(并且在其被清空之前)时,我们仅订阅最终的Observable(IList <>)序列。然而,在这个例子中,我们将使用Do操作符,当它们被原始序列(每秒一个整数)推出时,打印出值。当缓冲区已满时,我们使用Do操作符打印状态,然后将所有这些作为观察者订阅的最后序列。

var seq1 = Observable.Interval(TimeSpan.FromSeconds(1))           .Do(x => Console.WriteLine(x.ToString()))           .Buffer(5)           .Do(x => Console.WriteLine("buffer is full"))           .Subscribe(x => Console.WriteLine("Sum of the buffer is " + x.Sum()));Console.ReadKey();

  从此示例中可以看出,订阅位于一系列链接的可观察序列的收件人端。首先,我们使用Interval运算符创建一个可观察的整数序列,以秒为单位。然后,我们使用Buffer操作符将5个项目放入一个缓冲区中,并且只有当缓冲区已满时才将它们作为另一个序列发送出去。最后,这被交给Subscribe运算符。数据沿着所有这些中间序列传播,直到它们被推送到观察者。以相同的方式,订阅以与源序列相反的方向传播。通过在这样的传播过程中插入Do操作符,您可以对这种数据流进行“间谍”,就像在.NET中使用Console.WriteLine或在C中使用printf()执行调试一样。
  您还可以使用Timestamp运算符来验证项目按可观察序列推出的时间。这可以帮助您排除基于时间的操作,以确保准确性。回想一下创建和订阅简单可观察序列主题中的以下示例,其中我们将Timestamp运算符链接到查询,以便源序列推出的每个值将在发布时附加。通过这样做,当我们订阅这个源序列时,我们可以接收它的值和时间戳。

Console.WriteLine(“Current Time: “ + DateTime.Now);var source = Observable.Timer(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(1))                       .Timestamp();using (source.Subscribe(x => Console.WriteLine("{0}: {1}", x.Value, x.Timestamp)))      {           Console.WriteLine("Press any key to unsubscribe");           Console.ReadKey();      }Console.WriteLine("Press any key to exit");Console.ReadKey();

输出如下:
Current Time: 5/31/2011 5:35:08 PM
Press any key to unsubscribe
0: 5/31/2011 5:35:13 PM -07:00
1: 5/31/2011 5:35:14 PM -07:00
2: 5/31/2011 5:35:15 PM -07:00

通过使用Timestamp运算符,我们验证了第一个项目确实在序列之后5秒被推出,每个项目在1秒后发布。
此外,您还可以在lambda表达式中设置断点以协助调试。 通常,您只能为整个查询设置断点,而不必选择特定值来查看它。 要解决此限制,您可以在查询中间插入Select运算符,并在其中设置断点,并在Select语句中,使用自己的行上的return语句将相同的值投影到其源。 然后,您可以在返回语句行设置断点,并在查找值时检查值

var seq = Observable.Interval(TimeSpan.FromSeconds(1))          .Do(x => Console.WriteLine(x.ToString()))          .Buffer(5)          .Select(y => {                   return y; }) // set a breakpoint at this line          .Do(x => Console.WriteLine("buffer is full"))          .Subscribe(x => Console.WriteLine("Sum of the buffer is " + x.Sum()));Console.ReadKey();

  在此示例中,断点设置在返回y线。 当调试到程序中时,y变量显示在Locals窗口中,您可以检查其总数(5)。 如果您展开y,您还可以检查列表中的每个项目,包括其值和类型。
  或者,您可以将lambda表达式转换为语句lambda表达式,格式代码,以便语句在其自己的行上,然后设置断点。
  完成调试后,可以删除任何Do和Select调用。

0 0
原创粉丝点击