代码之家  ›  专栏  ›  技术社区  ›  BlackWasp

我能得到一系列的好结果和一个来自moq的异常吗?

moq
  •  6
  • BlackWasp  · 技术社区  · 15 年前

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

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

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

    1 回复  |  直到 9 年前
        1
  •  5
  •   Alireza    9 年前

    是的,如果你不介意跳过几个小圈圈,这是可能的。我以前为我的一个项目做过这个。好的,这是基本的技术。我刚在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异常的原因是队列类自动引发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));
    }