我使用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() – 2010-10-15 15:33:56
@Sergey Aldoukhov:我同意,但是PL的答案學會了我如何使用'物化'來推測我的IObservable行爲。對於使用變量來捕捉髮生的事情的更復雜的測試可能更難理解。另外,根據您的建議創建擴展可能會更容易理解正在發生的事情。 – 2010-10-15 16:01:32
我編輯了我的問題,使其更清楚我想要什麼。 – 2010-10-29 11:59:03