Sí, esto es posible si no te importa saltar a través de algunos aros menores. Ya hice esto para uno de mis proyectos. Bien, aquí está la técnica básica. Acabo de probar a cabo en Visual Studio 2008, y esto funciona:
var mockMessage1 = new Mock<IMessage>();
var mockMessage2 = new Mock<IMessage>();
var mockMessage3 = new Mock<IMessage>();
var messageQueue = new Queue<IMessage>(new [] { mockMessage1.Object, mockMessage2.Object, mockMessage3.Object });
var mockMsmqWrapper = new Mock<IMsmqWrapper>();
mockMsmqWrapper.Setup(x => x.GetMessage()).Returns(() => messageQueue.Dequeue()).Callback(() =>
{
if (messageQueue.Count == 0)
mockMsmqWrapper.Setup(x => x.GetMessage()).Throws<MyCustomException>();
});
Unas pocas notas:
- usted no tiene que devolver mensajes burlado, pero es útil si desea verificar las expectativas en cada mensaje también para ver si se llamaron ciertos métodos o se establecieron propiedades.
- La idea de la cola no es mía, solo un consejo que recibí de una publicación de blog.
- La razón por la que estoy lanzando una excepción de MyCustomException es porque la clase Queue arroja automáticamente una InvalidOperationException. Quería asegurarme de que el objeto MsmqWrapper burlado arroja una excepción debido a Moq y no a que la cola se quede sin elementos.
Aquí está el código completo que funciona. Tenga en cuenta que este código es feo en algunos lugares, pero yo sólo quería mostrar cómo esto podría ser probado:
public interface IMsmqWrapper
{
IMessage GetMessage();
}
public class MsmqWrapper : IMsmqWrapper
{
public IMessage GetMessage()
{
throw new NotImplementedException();
}
}
public class Processor
{
private IMsmqWrapper _wrapper;
public int MessagesProcessed { get; set; }
public bool ExceptionThrown { get; set; }
public Processor(IMsmqWrapper msmqWrapper)
{
_wrapper = msmqWrapper;
}
public virtual void ProcessMessages()
{
_wrapper.GetMessage();
MessagesProcessed++;
_wrapper.GetMessage();
MessagesProcessed++;
_wrapper.GetMessage();
MessagesProcessed++;
try
{
_wrapper.GetMessage();
}
catch (MyCustomException)
{
ExceptionThrown = true;
}
}
}
[Test]
public void TestMessageQueueGetsExhausted()
{
var mockMessage1 = new Mock<IMessage>();
var mockMessage2 = new Mock<IMessage>();
var mockMessage3 = new Mock<IMessage>();
var messageQueue = new Queue<IMessage>(new [] { mockMessage1.Object, mockMessage2.Object, mockMessage3.Object });
var mockMsmqWrapper = new Mock<IMsmqWrapper>();
mockMsmqWrapper.Setup(x => x.GetMessage()).Returns(() => messageQueue.Dequeue()).Callback(() =>
{
if (messageQueue.Count == 0)
mockMsmqWrapper.Setup(x => x.GetMessage()).Throws<InvalidProgramException>();
});
var processor = new Processor(mockMsmqWrapper.Object);
processor.ProcessMessages();
Assert.That(processor.MessagesProcessed, Is.EqualTo(3));
Assert.That(processor.ExceptionThrown, Is.EqualTo(true));
}
+1 Debido Moq es impresionante ;-) Me – toxvaerd
decir al respecto! Durante más de un año usé un determinado producto comercial cuyo nombre permanecerá sin decir aquí y ODIO burlándose. Tenía que leer y volver a leer constantemente la documentación cada vez. Moq es una bocanada de aire fresco. Pude usarlo en unos minutos y rara vez necesito leer la documentación. –
He estado usando RhinoMocks, pero pensé que iba a darle una oportunidad a Moq para ver cómo se compara y difundir mi conocimiento. Ahora soy un converso: encuentro la sintaxis de Moq más fácil de leer al escanear el código. – BlackWasp