1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[.NET Core] Moq と DI

Last updated at Posted at 2020-06-13

.NET Core で Moq と DI を使ってテストコードを実装する。

環境

  • Windows 10 Pro
  • Visual Studio 2019
  • .NET Core 3.1

準備

  • Visual Studio で 「xUnit テストプロジェクト(.NET Core)」を作成
  • 作成したテストプロジェクトに、NuGet パッケージの管理から「Moq」をインストール

実装

サンプルコード

Hoge.cs
    public interface IHoge
    {
        public int Value { get; set; }
        public int Calculate(int value);
        public int Calculate();
    }

    public class Hoge : IHoge
    {
        public int Value { get; set; }

        public int Calculate(int val) => val * 2;

        public int Calculate() => Calculate(Value);
    }
Fuga.cs
    public class Fuga
    {
        private IHoge hoge;

        public Fuga(IHoge hoge) => this.hoge = hoge;

        public int Calculate(int val) => hoge.Calculate(val);

        public int GetValue() => hoge.Value;

        public int Calculate() => hoge.Calculate();
    }

テストコード

UnitTest.cs
    public class UnitTest
    {
        private Mock<IHoge> hogeMock = new Mock<IHoge>();

        [Fact]
        public void Test1()
        {
            // Hoge.Calculate(int val) の戻り値に 6 を設定
            hogeMock.Setup(h => h.Calculate(It.IsAny<int>()))
                .Returns(6);

            var f = new Fuga(hogeMock.Object);
            Assert.Equal(6, f.Calculate(1));
        }
  • Test1
    • 引数の値に関わらず、固定で Calculate メソッドの戻り値を設定する。
UnitTest.cs
        [Fact]
        public void Test2()
        {
            // Hoge.Calculate(int val) 引数が 4 以下の場合、戻り値に 10 を設定
            hogeMock.Setup(h => h.Calculate(It.Is<int>(i => i <= 4)))
                .Returns(10);
            // Hoge.Calculate(int val) 引数が 5 以上の場合、戻り値に 20 を設定
            hogeMock.Setup(h => h.Calculate(It.Is<int>(i => i >= 5)))
                .Returns(20);

            var f = new Fuga(hogeMock.Object);
            Assert.Equal(20, f.Calculate(5));
        }
  • Test2
    • 引数の値によって、Calculate メソッドの戻り値を分岐させる。
UnitTest.cs
        [Fact]
        public void Test3()
        {
            // Hoge.Calculate(int val) ApplicationException が発生
            hogeMock.Setup(h => h.Calculate(It.IsAny<int>()))
                .Throws<ApplicationException>();

            var f = new Fuga(hogeMock.Object);
            Assert.Throws<ApplicationException>(() => f.Calculate(5));
        }
  • Test3
    • Calculate メソッドにて例外が発生した状態とする。
UnitTest.cs
        [Fact]
        public void Test4()
        {
            // Hoge.Value に 4 を設定
            hogeMock.SetupProperty(h => h.Value, 4);

            var f = new Fuga(hogeMock.Object);
            Assert.Equal(4, f.GetValue());
        }
  • Test4
    • Value プロパティに値を設定する。
UnitTest.cs
        [Fact]
        public void Test5()
        {
            // Hoge.Value setter に 3 を設定
            hogeMock.SetupSet(h => h.Value = 3);
            // Hoge.Value getter に 5 を設定
            hogeMock.SetupGet(h => h.Value)
                .Returns(5);

            var f = new Fuga(hogeMock.Object);
            // GetValue() で呼び出されるのは Hoge.Value getter
            Assert.Equal(5, f.GetValue());
        }
  • Test5
    • Value プロパティの setter と getter に異なる値を設定する。
    • Fuga.GetValue() は Hoge.Value の値を取得するため、Mock の getter が有効となる。
UnitTest.cs
        [Fact]
        public void Test6()
        {
            // Hoge.Calculate() の戻り値に 8 を設定
            hogeMock.Setup(h => h.Calculate())
                .Returns(8);
            // Hoge.Calculate(int val) の戻り値に 6 を設定
            hogeMock.Setup(h => h.Calculate(It.IsAny<int>()))
                .Returns(6);
            // Hoge.Value に 4 を設定
            hogeMock.SetupProperty(h => h.Value, 4);

            var f = new Fuga(hogeMock.Object);
            // Calculate() の戻り値に 8 を設定しているため、内部処理(Calculate(int val)、Value)の設定は意味を持たない
            Assert.Equal(8, f.Calculate());
        }
  • Test6
    • 引数なし Calculate メソッド、引数あり Calculate メソッド、Value プロパティに値を設定する。
    • Fuga.Calculate() は Hoge.Calculate() の値を取得するため、Mock の引数なし Calculate メソッドが有効となる。
    • Mock の引数あり Calculate メソッド、Value プロパティの値が利用されていないことが確認できる。

使いどころ

  • Controller など、依存するモジュールが多いクラスのテスト実装の際に特に便利。
  • パラメータによる戻り値の分岐や、例外発生などができるため、広範囲にテストが実施できる。
  • より複雑なことをしたい場合は、下記サイトをより詳細に読み込むのが良し。

Log の Verify について

別記事書きました
[.NET Core] xUnit で log を verify する

参考

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?