【C#】【Mock】Moq ~ サンプルコード編 ~

■ サンプル

モック対象インターフェイス

namespace NUnitForm
{
    public interface ISampleInterface
    {
        int Sum(int value1, int value2);
        int Max(int value1, int value2);
    }
}

テストコード

using System;
using NUnit.Framework;
using Moq; // 追加
using NUnitForm;

namespace FormTest
{
    [TestFixture] // テストコードであることを表すために[TestFixture]属性をクラスにつける
    public class TestClass
    {
        Mock<ISampleInterface> mock;

        [SetUp] // テストコードの初期化のために[SetUp]属性をメソッドにつける
        public void SetUp()
        {
            // Mock作成
            this.mock = new Mock<ISampleInterface>();

            // Sum()が第一引数「1」、第二引数「2」で呼ばれたら「3」を返すように設定
            this.mock.Setup(x => x.Sum(1, 2)).Returns(3);
            // Sum()が第一引数「5」、第二引数「5」で呼ばれたら「10」を返すように設定
            this.mock.Setup(x => x.Sum(5, 5)).Returns(10);
            // Sum()が第一引数「6」、第二引数「5」で呼ばれたら「11」を返すように設定
            int num1 = 11;
            this.mock.Setup(x => x.Sum(6, 5)).Returns(num1);
            // Sum()が第一引数「6」、第二引数「0」で呼ばれたら「6」を返すように設定
            int num2 = 6;
            this.mock.Setup(x => x.Sum(6, 0)).Returns(() => num2);

            // Sum()が第一引数「4」、第二引数「3」で呼ばれたら「7」を返すように設定
            // 1回だけ呼び出し可能
            this.mock.Setup(m => m.Sum(4, 3)).Returns(7).AtMostOnce();
            // Sum()が第一引数「7」、第二引数「2」で呼ばれたら「9」を返すように設定
            // 2回だけ呼び出し可能(1回もOK、3回目からエラー)
            this.mock.Setup(m => m.Sum(7, 2)).Returns(9).AtMost(2);

            // Sum()が第一引数「2」、第二引数「2」で呼ばれたら例外を返すように設定
            this.mock.Setup(m => m.Sum(2, 2)).Throws<ArgumentException>();
            // Sum()が第一引数「3」、第二引数「3」で呼ばれたら例外を返すように設定
            this.mock.Setup(m => m.Sum(3, 3)).Throws(new ArgumentException());

            // Sum()が第一引数「4」、第二引数「4」で呼ばれたら「8」を返すように設定
            this.mock.Setup(x => x.Sum(4, 4)).Returns(8).Callback((int x, int y) => Console.WriteLine(x + y));
            // Sum()が第一引数「6」、第二引数「7」で呼ばれたら「13」を返すように設定
            this.mock.Setup(x => x.Sum(6, 7)).Returns(13).Callback<int, int>((x, y) => Console.WriteLine(x + y));

            // Max(引数が何でも良い)で呼ばれたら「10」を返すように設定
            this.mock.Setup(x => x.Max(It.IsAny<int>(), It.IsAny<int>())).Returns(10);
        }

        [Test] // テスト項目を表すために[TestFixture]属性をメソッドにつける
        public void Test_Sum()
        {
            // Mockオブジェクト取得
            var obj = mock.Object;

            // Sum()が第一引数「1」、第二引数「2」で呼ぶ
            Assert.AreEqual(3, obj.Sum(1, 2));
            // Sum()が第一引数「5」、第二引数「5」で呼ぶ
            Assert.AreEqual(10, obj.Sum(5, 5));
            // Sum()が第一引数「6」、第二引数「5」で呼ぶ
            Assert.AreEqual(11, obj.Sum(6, 5));

            // Sum()が第一引数「4」、第二引数「3」で呼ぶ
            Assert.AreEqual(7, obj.Sum(4, 3));
            // Sum()が第一引数「7」、第二引数「2」で呼ぶ
            Assert.AreEqual(9, obj.Sum(7, 2));
            Assert.AreEqual(9, obj.Sum(7, 2));

            // Sum()が第一引数「2」、第二引数「1」で呼ぶ
            // 設定してないと、0を返す
            Assert.AreEqual(0, obj.Sum(2, 1));

            // Sum()が第一引数「2」、第二引数「2」で呼ぶ
            //Assert.AreEqual(4, obj.Sum(2, 2)); // 例外発生
            // Sum()が第一引数「3」、第二引数「3」で呼ぶ
            //Assert.AreEqual(6, obj.Sum(3, 3)); // 例外発生

            // Sum()が第一引数「4」、第二引数「4」で呼ぶ
            // (NUnitの「Test outout」タブに「8」と出力される)
            Assert.AreEqual(8, obj.Sum(4, 4));
            // Sum()が第一引数「6」、第二引数「7」で呼ぶ
            Assert.AreEqual(13, obj.Sum(6, 7));

            // Max()が第一引数「6」、第二引数「7」で呼ぶ
            Assert.AreEqual(10, obj.Max(6, 7));

            //モックの振る舞いが呼び出されたかを確認
            //mock.Verify();
            mock.Verify(x => x.Sum(5, 5), Times.Once());
        }
    }
}


関連記事

Moq関連

Moq ~ 初期設定編 ~
https://blogs.yahoo.co.jp/dk521123/21212662.html
Moq ~ 文法編 ~
https://blogs.yahoo.co.jp/dk521123/21216313.html
Moq ~ サンプルコード編 ~
https://blogs.yahoo.co.jp/dk521123/21217266.html