【发布时间】:2010-10-12 14:25:20
【问题描述】:
我使用Reactive Extensions for .NET (Rx) 将事件公开为IObservable<T>。我想创建一个单元测试,我断言触发了特定事件。这是我要测试的类的简化版本:
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,这使得测试变得更加容易。
这是我的测试方法:
// Arrange
var classUnderTest = new ClassUnderTest();
var eventFired = false;
classUnderTest.SomethingHappened.Subscribe(_ => eventFired = true);
// Act
classUnderTest.DoSomething();
// Assert
Assert.IsTrue(eventFired);
使用变量来确定是否触发了事件并不算太糟糕,但在更复杂的场景中,我可能想要验证是否触发了特定的事件序列。如果不简单地将事件记录在变量中,然后对变量进行断言,这是否可能?能够使用流畅的类似 LINQ 的语法对 IObservable 进行断言有望使测试更具可读性。
【问题讨论】:
-
顺便说一句,我认为有一个变量是非常好的。上面的代码很容易阅读,这是最重要的。 @PL 的答案很好很优雅,但你必须努力理解发生了什么......也许将其转换为扩展 FailIfNothingHappened()
-
@Sergey Aldoukhov:我同意,但是 PL 的回答让我知道了如何使用
Materialize来推断我的IObservable的行为方式。而对于更复杂的测试,使用变量来捕捉所发生的事情可能更难理解。此外,按照您的建议创建一个扩展程序可能会更容易理解发生了什么。 -
我已经编辑了我的问题,以便更清楚我想要什么。
标签: c# .net unit-testing system.reactive