NDW

アプリ開発やトラブルシューティング等のノウハウ、キャンプや登山の紹介や体験談など。

.NET Core 1. システムエンジニアリング 実装技術

.NET Core(C#): MoqのSetupProperty()/SetupGet()/SetupSet()の違い

投稿日:

はじめに

SetupProperty()/SetupGet()/SetupSet()の違い

  • SetupProperty()、SetupSet()/SetupGet()と併せて使用されるVerify(), VerifyGet()/VerifySet()の違いは次の通りです。
    SetupSet()/SetupGet()系は誤解を招く場合があるので、基本的にはSetupProperty()を使用することを強くおすすめします。
    項目 SetupProperty() SetupSet(), SetupGet()
    ,Verify(), VerifyGet()/VerifySet()
    用途 追跡可能なプロパティの準備 プロパティ値の設定・取得回数の検証
    設定値の保持と取得 可能 不可
    最新のプロパティ値の検証 可能 不可
    過去のプロパティ値の検証 不可 可能
    (値毎の回数を検証可、順番の検証不可)
    プロパティ値の取得回数 不可 可能
    プロパティ値の設定回数 不可 可能
  • SetupProperty()で準備したプロパティは、一般的なプロパティと同様に値の設定や取得が可能です。
    プロパティに設定されている最終的な値が期待したものかを検証することができます。
    var targetMock = new Mock<ITarget>();
    ITarget target = targetMock.Object;
    
    targetMock.SetupProperty(o => o.StrProp);
    
    target.StrProp = "test";
    Assert.Equal("test", target.StrProp);
    
  • プロパティ(やメソッド)が実行されたかは、SetupGet()/SetupSet()とMock.Verify()で検証できます。
    var targetMock = new Mock<ITarget>();
    ITarget target = targetMock.Object;
    
    // 一括検証(Verify)の対象とするためにVerifiable()を指定
    targetMock
        .SetupGet(o => o.StrProp)
        .Verifiable();
    targetMock
        .SetupSet(o => o.IntProp = 100) // 検証時の期待値(初期値設定ではない!)
        .Verifiable();
    
    _ = target.StrProp;
    target.IntProp = 1;
    target.IntProp = 100;
    target.IntProp = 100;
    target.IntProp = 200;
    
    targetMock.Verify(); // 一括検証(検証対象を纏めて検証)
    
    // 値を保持していないので、最終的な値を検証できない。
    //Assert.Equal(200, target.IntProp); // NG
    Assert.Equal(0, target.IntProp);
    
    • プロパティ値の取得が実行されたか(getter呼び出し回数が1回以上)を検証する場合、SetupGet()で対象プロパティを指定します。プロパティ値に特定値が設定されたか(setter呼び出し回数が1回以上)を検証する場合、SetupSet()で対象プロパティと期待値を指定します。
      また、Verify()の検証対象とするために、各SetupGet()/SetupSet()に対して、Verifiable()を実行する必要があります。
    • SetupSet()で指定する値は、次のように2重、3重に誤解を招くので、利用には注意が必要です。
      1. 期待値が「プロパティの初期値」のように見える。
      2. 検証では「プロパティに期待値が1回以上設定されたことを検証」するのであって、「プロパティ値と期待値の一致を検証」するわけではありません。(上記のサンプルでは、IntPropプロパティ値として100を検証していますが、一度でも100が設定されれば良いので、最終的に200が設定されても検証が成功してしまいます。)
      3. SetupSet()を実行すると、SetupProperty()のようにプロパティ値が保持されるように見えます。実際には「プロパティ値に期待値が設定されたか」の情報しかなく、プロパティ値は保持されていません。(上記のサンプルでは、IntPropに100や200を設定していますが、取得できるプロパティ値は既定値0のみです。)
    • Mock.Verify()では「プロパティのgetter/setterが1回以上実行されたかどうか」の検証しかできません。1回のみ実行された、2回以上実行された、実行されていない、等の細かい条件を指定する場合は、次のMock.VerifyGet(), Mock.VerifySet()を使用する必要があります。
  • プロパティ(やメソッド)の実行回数を細かい条件で検証する場合は、Mock.VerifySet(), Mock.VerifyGet()を使用します。Verify()とは異なり、検証対象のプロパティや期待値を直接指定するので、SetupGet()/SetupSet()は不要です。
    var targetMock = new Mock<ITarget>();
    ITarget target = targetMock.Object;
    
    _ = target.StrProp;
    target.IntProp = 1;
    target.IntProp = 100;
    target.IntProp = 100;
    target.IntProp = 200;
    
    targetMock.VerifyGet(o => o.StrProp); // 1回のみ(既定)
    targetMock.VerifySet(o => o.IntProp = 100, Times.Exactly(2)); // 2回
    targetMock.VerifySet(o => o.IntProp = 300, Times.Never); // 0回
    
    // 値を保持していないので、最終的な値を検証できない。
    //Assert.Equal(200, target.IntProp); // NG
    Assert.Equal(0, target.IntProp);
    
    • プロパティ値の取得回数、プロパティに設定された値とその回数を検証できますが、同様にプロパティ値を保持しないので最終的なプロパティ値を検証できません。
    • 指定可能な実行回数(Times)は次通りです。
      (”n”は実行回数、”a”, “b”は実行回数の条件を決定するための引数)
      項目 説明
      Times.AtLeast(a) 最小回数(n >= a)
      Times.AtLeastOnce 1回以上(n >= 1)
      Times.AtMost(a) 最大回数(n <= a)
      Times.AtMostOnce 最大1回=0回か1回(n <= 1)
      Times.Between(a, b) a 回からb 回の間(a <= n <= b)
      Times.Exactly(a) a 回(n = a)
      Times.Never 0回(n = 0)
      Times.Once 1回(n = 1)






-.NET Core, 1. システムエンジニアリング, 実装技術

関連記事

IIS Expressでカスタムドメインと自己署名証明書

シングルサインオンの検証等を想定し、開発環境の複数のWebアプリに独自ドメイン名+SSLを使用したい。 Visual Studio 2019で作成したWeb系プロジェクトを前提とし、IIS Expre …

C#: キー・値の順番を保持してJSONをデシリアライズ

はじめに キー・値形式のJSONを解析する場合、JsonSerializer.Deserialize<Dictionary<T, V>>()を使って簡単に実現できますが、キー・ …

技術検証

Linuxでの gdrive の使い方

2020年現在、認証時にGoogleにブロックされることや、ツールのメンテナンスが終了していることもあり、rclone等の別のツールをお薦めします。 前提 使用した環境は次の通り。 OSはCentOS …

Hyper-VでリモートのISOイメージをマウント

皆で使用するCD/DVDはISOイメージファイルとして、ファイルサーバ上の共有フォルダに配置する運用を想定しています。Hyper-V上の仮想マシンのCD/DVDドライブに、これらのISOイメージファイ …

Graph API実行環境の準備方法(クライアント資格情報フローのアプリ登録)

概要 WebアプリからGraphAPIを使用してAzure AD B2C上のユーザアカウントの操作を行うことを想定しています。このような構成でGraph APIを使用できるようにするためのAzure …