6

MSMQ のラッパーをモックしています。ラッパーは、MessageQueue クラスの静的メソッドを直接呼び出すオブジェクト インスタンスを作成できるようにするだけです。

キューを使い果たすまでテストしたいと思います。これを行うには、モック化されたラッパーがいくつかの良い結果を返し、同じメソッドへの 4 回目の呼び出しで例外をスローするようにします。このメソッドはパラメーターを受け入れず、標準のメッセージ オブジェクトを返します。

Moqのメソッドでこの一連の期待を設定できますか?

4

1 に答える 1

5

うん、いくつかの小さなフープを飛び越えることを気にしないのであれば、これは可能です. 私は以前に自分のプロジェクトの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));
}
于 2009-06-12T09:26:37.750 に答える