.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()で準備したプロパティは、一般的なプロパティと同様に値の設定や取得が可能です。
    プロパティに設定されている最終的な値が期待したものかを検証することができます。
  • プロパティ(やメソッド)が実行されたかは、SetupGet()/SetupSet()とMock.Verify()で検証できます。
    • プロパティ値の取得が実行されたか(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()は不要です。
    • プロパティ値の取得回数、プロパティに設定された値とその回数を検証できますが、同様にプロパティ値を保持しないので最終的なプロパティ値を検証できません。
    • 指定可能な実行回数(Times)は次通りです。
      (”n”は実行回数、”a”, “b”は実行回数の条件を決定するための引数)

      項目説明
      Times.AtLeast(a)最小回数(n >= a)
      Times.AtLeastOnce1回以上(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.Never0回(n = 0)
      Times.Once1回(n = 1)