Estoy usando Reactive Extensions for .NET (Rx) para exponer eventos como IObservable<T>
. Quiero crear una prueba unitaria donde afirme que un evento particular se disparó. Aquí hay una versión simplificada de la clase que quiero probar:Pruebas unitarias para un evento usando Extensiones reactivas
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();
}
}
Obviamente, mis clases reales son más complejas. Mi objetivo es verificar que realizar algunas acciones con la clase bajo prueba conduce a una secuencia de eventos señalados en el IObservable
. Afortunadamente, las clases que deseo probar implementan IDisposable
y llaman al OnCompleted
sobre el tema cuando el objeto es eliminado hace que sea mucho más fácil de probar.
Aquí es cómo puedo probar:
// Arrange
var classUnderTest = new ClassUnderTest();
var eventFired = false;
classUnderTest.SomethingHappened.Subscribe(_ => eventFired = true);
// Act
classUnderTest.DoSomething();
// Assert
Assert.IsTrue(eventFired);
Usando una variable para determinar si un evento se dispara no es tan malo, pero en escenarios más complejos es posible que quiera verificar que una secuencia particular de los eventos están despedido. ¿Es eso posible sin simplemente registrar los eventos en variables y luego hacer aserciones sobre las variables? Sería bueno poder hacer la prueba para poder utilizar una sintaxis fluida de tipo LINQ para realizar afirmaciones en un IObservable
.
Por cierto, creo que tener una variable es perfectamente bueno. El código anterior es fácil de leer, que es lo más importante. La respuesta de @PL es agradable y elegante, pero tienes que esforzarte para entender lo que está pasando ... Tal vez transformarlo en una extensión FailIfNothingHappened() –
@Sergey Aldoukhov: Estoy de acuerdo, pero la respuesta de PL me enseñó cómo puedo usar ' Materialise' para razonar sobre cómo se comporta mi 'IObservable'. Y para las pruebas más complejas que usan variables para capturar lo que sucedió puede ser más difícil de entender. Además, la creación de una extensión tal como sugiere probablemente le facilitará la comprensión de lo que está sucediendo. –
He editado mi pregunta para que quede más claro lo que quiero. –