Могу ли я получить серию хороших результатов и выброшенное исключение из Moq

Я издеваюсь над оболочкой MSMQ. Оболочка просто позволяет создать экземпляр объекта, который напрямую вызывает статические методы класса MessageQueue.

Хочу проверить чтение очереди до изнеможения. Для этого я бы хотел, чтобы фиктивная оболочка возвращала хорошие результаты и генерировала исключение при четвертом вызове того же метода. Метод не принимает параметров и возвращает стандартный объект сообщения.

Могу ли я установить эту серию ожиданий от метода в Moq?


moq
person BlackWasp    schedule 12.06.2009    source источник
comment
+1 Потому что Moq классный ;-)   -  person toxvaerd    schedule 12.06.2009
comment
Расскажи мне об этом! Более года я использовал некий коммерческий продукт, название которого здесь не упоминается, и Я НЕНАВИЛ насмехаться над ним. Мне приходилось постоянно читать и каждый раз перечитывать документацию. Moq - это глоток свежего воздуха. Я смог использовать его за несколько минут, и мне редко нужно читать документацию.   -  person Praveen Angyan    schedule 12.06.2009
comment
Я использовал RhinoMocks, но я подумал, что попробую Moq, чтобы посмотреть, как он сравнивается, и поделиться своими знаниями. Теперь я новообращенный - мне легче читать синтаксис Moq при сканировании кода.   -  person BlackWasp    schedule 13.06.2009


Ответы (1)


Ага, это возможно, если вы не против прыгнуть через несколько второстепенных обручей. Я делал это раньше для одного из своих проектов. Хорошо, вот основная техника. Я только что протестировал его в 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));
}
person Praveen Angyan    schedule 12.06.2009