我可以从Moq获得一系列好结果和抛出的异常吗?

时间:2009-06-12 08:36:56

标签: moq

我正在嘲笑MSMQ的包装器。包装器只允许创建一个直接调用MessageQueue类的静态方法的对象实例。

我想测试读取队列是否用尽。为此,我希望模拟的包装器返回一些好的结果,并在第四次调用同一方法时抛出异常。该方法不接受任何参数并返回标准消息对象。

我可以对Moq中的方法设置这一系列期望吗?

1 个答案:

答案 0 :(得分:5)

是的,如果你不介意跳过一些小箍,这是可能的。我以前为我的一个项目做过这个。好的,这是基本技术。我刚刚在Visual Studio 2008中对它进行了测试,结果如下:

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>();
});

一些注意事项:

  1. 您不必返回模拟消息,但如果您想验证每条消息的期望以及是否调用了某些方法或设置了属性,那么它很有用。
  2. 队列的想法不是我自己的,只是我从博客文章中得到的一个提示。
  3. 我抛出MyCustomException异常的原因是Queue类自动抛出InvalidOperationException。我想确保模拟的MsmqWrapper对象因为Moq而抛出异常,而不是因为队列耗尽了项目。
  4. 这是完整的代码。请记住,这些代码在某些地方很难看,但我只是想告诉你如何测试它:

    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));
    }