2009-06-12 5 views
6

Estoy burlando de un contenedor a un MSMQ. El contenedor simplemente permite crear una instancia de objeto que llama directamente a los métodos estáticos de la clase MessageQueue.¿Puedo obtener una serie de buenos resultados y una excepción arrojada de Moq

Quiero probar la lectura de la cola hasta el agotamiento. Para hacer esto, me gustaría que el contenedor simulado devuelva algunos buenos resultados y lanzar una excepción en la cuarta llamada al mismo método. El método no acepta parámetros y devuelve un objeto de mensaje estándar.

¿Puedo configurar esta serie de expectativas sobre el método en Moq?

+0

+1 Debido Moq es impresionante ;-) Me – toxvaerd

+0

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. –

+0

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

Respuesta

5

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:

  1. 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.
  2. La idea de la cola no es mía, solo un consejo que recibí de una publicación de blog.
  3. 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)); 
} 
Cuestiones relacionadas