インデックス付きプロパティをMOQする方法


82

インデックス付きプロパティへの呼び出しをモックしようとしています。つまり、私は以下をmoqしたいと思います:

object result = myDictionaryCollection["SomeKeyValue"];

また、セッター値

myDictionaryCollection["SomeKeyValue"] = myNewValue;

アプリが使用するクラスの機能をモックする必要があるため、これを行っています。

誰かがMOQでこれを行う方法を知っていますか?私は以下のバリエーションを試しました:

Dictionary<string, object> MyContainer = new Dictionary<string, object>();
mock.ExpectGet<object>( p => p[It.IsAny<string>()]).Returns(MyContainer[(string s)]);

しかし、それはコンパイルされません。

私がMOQで達成しようとしていることは可能ですか?誰かが私がこれを行う方法の例を持っていますか?


スタブオブジェクトを使用する方が簡単ではないでしょうか。必要な値を設定し、必要なインデックスを確認してください。
セーレンは、ルンドスペル

回答:


96

モックの宣言を表示していないため、何をしようとしているのかが明確ではありません。辞書をモックしようとしていますか?

MyContainer[(string s)] 有効なC#ではありません。

これはコンパイルします:

var mock = new Mock<IDictionary>();
mock.SetupGet( p => p[It.IsAny<string>()]).Returns("foo");

1
これも同様に機能します。ただし、新しい構文では。のSetupSet代わりにを使用しますExpectGet。セッターにも使用できます。
tmont 2010

1
IDictionaryはSystem.Collectionsからのものであり、System.Collections.Genericからのものではありません
upInCloud 2016

20

Ash、HTTPセッションのモックが必要な場合は、次のコードがその役割を果たします。

/// <summary>
/// HTTP session mockup.
/// </summary>
internal sealed class HttpSessionMock : HttpSessionStateBase
{
    private readonly Dictionary<string, object> objects = new Dictionary<string, object>();

    public override object this[string name]
    {
        get { return (objects.ContainsKey(name)) ? objects[name] : null; }
        set { objects[name] = value; }
    }
}

/// <summary>
/// Base class for all controller tests.
/// </summary>
public class ControllerTestSuiteBase : TestSuiteBase
{
    private readonly HttpSessionMock sessionMock = new HttpSessionMock();

    protected readonly Mock<HttpContextBase> Context = new Mock<HttpContextBase>();
    protected readonly Mock<HttpSessionStateBase> Session = new Mock<HttpSessionStateBase>();

    public ControllerTestSuiteBase()
        : base()
    {
        Context.Expect(ctx => ctx.Session).Returns(sessionMock);
    }
}

ニース1 -これは私が1必要なものだけだった
イアン・オクスリー

1
このコードのどの部分で、テスト対象のコードにモックセッションを使用させますか?TestSuiteBase図書館ですか、それともあなた自身のクラスですか?
StuperUser 2011

1
それはモックではなく、偽物です。ただ言って。
クリス・ピーコック

17

正しく見つけたように、ゲッターとセッターをそれぞれ初期化するための異なるメソッドがSetupGetありSetupSetます。けれどもはSetupGetプロパティ、インデクサないために使用されることが意図され、そしてあなたがそれに渡されたキーを扱うことはできません。正確には、インデクサーSetupGetSetupとにかく呼び出すでしょう:

internal static MethodCallReturn<T, TProperty> SetupGet<T, TProperty>(Mock<T> mock, Expression<Func<T, TProperty>> expression, Condition condition) where T : class
{
  return PexProtector.Invoke<MethodCallReturn<T, TProperty>>((Func<MethodCallReturn<T, TProperty>>) (() =>
  {
    if (ExpressionExtensions.IsPropertyIndexer((LambdaExpression) expression))
      return Mock.Setup<T, TProperty>(mock, expression, condition);
    ...
  }
  ...
}

あなたの質問に答えるために、これはDictionary値を格納するために基礎を使用するコードサンプルです:

var dictionary = new Dictionary<string, object>();

var applicationSettingsBaseMock = new Mock<SettingsBase>();
applicationSettingsBaseMock
    .Setup(sb => sb[It.IsAny<string>()])
    .Returns((string key) => dictionary[key]);
applicationSettingsBaseMock
    .SetupSet(sb => sb["Expected Key"] = It.IsAny<object>())
    .Callback((string key, object value) => dictionary[key] = value);

ご覧のとおり、インデクサーセッターを設定するには、キーを明示的に指定する必要があります。詳細は別のSOの質問で説明されていますインデックス付きプロパティをMoqし、リターン/コールバックでインデックス値を使用します


1
これが私が探していたものです!他の例はどれも機能しませんでした
フィオナ-myaccessible.website 2018

8

それほど難しいことではありませんが、見つけるのに少し時間がかかりました:)

var request = new Moq.Mock<HttpRequestBase>();
request.SetupGet(r => r["foo"]).Returns("bar");

-4

私がMOQでやろうとしていたことは不可能のようです。

基本的に、HTTPSessionタイプのオブジェクトをMOQしようとしていました。このオブジェクトでは、インデックスに設定されているアイテムのキーは実行時にのみ決定できました。以前に設定された値を返すために必要なインデックス付きプロパティへのアクセス。これは整数ベースのインデックスでは機能しますが、文字列ベースのインデックスは機能しません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.