Estoy escribiendo la prueba de la unidad y recibo una excepción cuando trato de plantear el evento de la simulación de la clase abstracta. Aquí está el código de ejemplo:C# y Moq, plantear el evento declarado en la interfaz de la clase de simulacro
public abstract class AbstractBase : EntityObject
{}
[TestMethod]
public void MyTest()
{
var mock = new Mock<AbstractBase>();
var notificationMock = entityMock.As<INotifyPropertyChanged>();
var propertyChangedMapper = new PropertyChangedMapper();
bool eventReceived = false;
propertyChangedMapper.MyPropertyChanged +=
(sender, eventArgs) =>
{
eventReceived = true;
};
propertyChangedMapper.Subscribe((AbstractBase)notificationMock.Object);
Assert.IsFalse(eventReceived);
notificationMock.Raise(e=>e.PropertyChanged += null,
new PropertyChangedEventArgs("Property1"));
Assert.IsTrue(eventReceived);
}
Obviamente, podría utilizar simulacro en INotifyPropertyChanged
y el evento se ha levantado muy bien, pero en el interior de PropertyChangedMapper
necesito a emitir el emisor a AbstractBase
el que falla si se utiliza Mock<INotifyPropertyChanged>
EDITAR: Según sugerencia usando Mock.As<>()
parece ser el camino correcto, el único problema anterior es que el evento resucitado de notificationMock
no tiene nada que ver con la simulación original del objeto. Código:
notificationMock.Object.PropertyChanged += (s, e) =>
{
var result = "this one is fired as it should";
};
mock.Object.PropertyChanged += (s, e) =>
{
var result = "this one is not called but is actually what I need";
};
notificationMock.Raise(e => e.PropertyChanged += null,
new PropertyChangedEventArgs("Property1"));
No importa a cuál llame, siempre que se llame. Mi suposición es que podrías configurar uno u otro. Pero establecer ambas conducirá al simulacro de elegir internamente una sobre otra. –
Para obtener más pruebas de que no importa a qué se llama, considere que el sistema de tipo funciona de manera similar para los miembros virtuales y sus reemplazos. Por ejemplo, si agregó a AbstractBase una anulación para el evento INPC de EntityObject, no hay forma de que ningún código que consuma AbstractBase fuerce la invocación de la versión de EntityObject. Incluso si seleccionas EntityObject, se llamará al miembro de AbstractBase. Una vez que se invalida un miembro base, solo la clase derivada puede acceder al miembro base original. –