6

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

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

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

4

1 回答 1

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 而不是因为队列用完项目而引发异常。

这是有效的完整代码。请记住,这段代码在某些地方很难看,但我只是想向您展示如何测试它:

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));
}
于 2009-06-12T09:26:37.750 回答