使用响应式扩展对事件进行单元测试 [英] Unit testing for an event using Reactive Extensions

查看:42
本文介绍了使用响应式扩展对事件进行单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 .NET(Rx)的反应扩展将事件显示为 IObservable< T> .我想创建一个单元测试,在其中断言某个特定事件已被触发.这是我要测试的类的简化版本:

I'm using Reactive Extensions for .NET (Rx) to expose events as IObservable<T>. I want to create an unit test where I assert that a particular event is fired. Here is a simplified version of the class I want to test:

public sealed class ClassUnderTest : IDisposable {

  Subject<Unit> subject = new Subject<Unit>();

  public IObservable<Unit> SomethingHappened {
    get { return this.subject.AsObservable(); }
  }

  public void DoSomething() {
    this.subject.OnNext(new Unit());
  }

  public void Dispose() {
    this.subject.OnCompleted();
  }

}

很明显,我的真实课堂更加复杂.我的目标是验证对被测类执行某些操作是否会导致在 IObservable 上发出信号的一系列事件.幸运的是,我要测试的类实现了 IDisposable ,并在对象被放置后在主题上调用 OnCompleted 使得测试变得更加容易.

Obviously my real classes are more complex. My goal is to verify that performing some actions with the class under test leads to a sequence of events signaled on the IObservable. Luckily the classes I want to test implement IDisposable and calling OnCompleted on the subject when the object is disposed makes it much easier to test.

这是我的测试方式:

// Arrange
var classUnderTest = new ClassUnderTest();
var eventFired = false;
classUnderTest.SomethingHappened.Subscribe(_ => eventFired = true);

// Act
classUnderTest.DoSomething();

// Assert
Assert.IsTrue(eventFired);

使用变量来确定是否触发了一个事件并不太坏,但是在更复杂的情况下,我可能要验证是否触发了特定的事件序列.如果不简单地将事件记录在变量中,然后对变量进行断言,是否有可能?能够使用流畅的类似LINQ的语法对 IObservable 进行断言,有望使测试更具可读性.

Using a variable to determine if an event is fired isn't too bad, but in more complex scenarios I may want to verify that a particular sequence of events are fired. Is that possible without simply recording the events in variables and then doing assertions on the variables? Being able to use a fluent LINQ-like syntax to make assertions on an IObservable would hopefully make the test more readable.

推荐答案

此答案已更新为现在发布的Rx 1.0版.

This answer has been updated to the now released version 1.0 of Rx.

官方文档仍然很少,但是测试和调试可观察序列是一个很好的起点.

Official documentation is still scant but Testing and Debugging Observable Sequences on MSDN is a good starting place.

测试类应从 < Microsoft.Reactive.Testing 名称空间中的code> ReactiveTest .该测试基于 TestScheduler 为测试提供虚拟时间.

The test class should derive from ReactiveTest in the Microsoft.Reactive.Testing namespace. The test is based around a TestScheduler that provides virtual time for the test.

TestScheduler.Schedule 方法可用于将活动在虚拟时间的某些点(滴答声)排队.该测试由 TestScheduler.Start 执行.这将返回一个 ITestableObserver< T> ,例如,可以通过使用 ReactiveAssert 类将其用于断言.

The TestScheduler.Schedule method can be used to queue up activities at certain points (ticks) in virtual time. The test is executed by TestScheduler.Start. This will return an ITestableObserver<T> that can be used for asserting for instance by using the ReactiveAssert class.

public class Fixture : ReactiveTest {

  public void SomethingHappenedTest() {
    // Arrange 
    var scheduler = new TestScheduler();
    var classUnderTest = new ClassUnderTest();

    // Act 
    scheduler.Schedule(TimeSpan.FromTicks(20), () => classUnderTest.DoSomething());
    var actual = scheduler.Start(
      () => classUnderTest.SomethingHappened,
      created: 0,
      subscribed: 10,
      disposed: 100
    );

    // Assert
    var expected = new[] { OnNext(20, new Unit()) };
    ReactiveAssert.AreElementsEqual(expected, actual.Messages);
  }

}

TestScheduler.Schedule 用于安排在时间20(以滴答为单位)对 DoSomething 的呼叫.

TestScheduler.Schedule is used to schedule a call to DoSomething at time 20 (measured in ticks).

然后 TestScheduler.Start 用于对可观察的 SomethingHappened 进行实际测试.订阅的生存期由调用的参数控制(再次以滴答表示).

Then TestScheduler.Start is used to perform the actual test on the observable SomethingHappened. The lifetime of the subscription is controlled by the arguments to the call (again measured in ticks).

最后, ReactiveAssert.AreElementsEqual 用于验证是否按预期在时间20调用了 OnNext .

Finally ReactiveAssert.AreElementsEqual is used to verify that OnNext was called at time 20 as expected.

该测试验证调用 DoSomething 会立即触发可观察到的 SomethingHappened .

The test verifies that calling DoSomething immediately fires the observable SomethingHappened.

这篇关于使用响应式扩展对事件进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆