Як 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, чи є у когось приклади того, як я можу це зробити?


Чи не було б простіше просто використовувати об'єкт заглушки? Встановіть необхідні значення та перевірте потрібні індекси.
Søren Spelling Lund

Відповіді:


96

Незрозуміло, що ви намагаєтеся зробити, тому що ви не показуєте декларацію насмішки. Ви намагаєтеся знущатися зі словника?

MyContainer[(string s)] недійсний C #.

Це компілює:

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

1
це також працює. за винятком використання нового синтаксису SetupSetзамість ExpectGet. також працює для сетерів.
tmont

1
Ідентифікатор від System.Collections, а не від System.Collections.Generic
upInCloud

20

Еш, якщо ви хочете мати макет HTTP Session, тоді цей фрагмент коду виконує цю роботу:

/// <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
Ian Oxley

1
Яка частина цього коду змушує тестований код використовувати макетний сеанс? Є чи TestSuiteBaseбібліотека або ваш власний клас?
StuperUser

1
Це не знущання, це підробка. Просто кажу.
Chris Peacock

17

Як ви правильно помітили, існують різні методи SetupGetі SetupSetдля ініціалізації геттерів та сеттерів відповідно. Хоча SetupGetпризначений для використання для властивостей, а не для індексів, і не дозволить вам обробляти переданий йому ключ. Якщо бути точним, то індексатори SetupGetвсе Setupодно зателефонують :

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
Це те, що я шукав !! Жоден з інших прикладів не працював
Fiona - myaccessible.website

8

Це не так складно, але знадобилося трохи, щоб знайти його :)

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

-4

Здається, те, що я намагався зробити з MOQ, неможливо.

По суті, я намагався MOQ об’єкт типу HTTPSession, де ключ елемента, якому встановлюється індекс, можна було визначити лише під час виконання. Доступ до властивості, що індексується, необхідний для повернення значення, яке було встановлено раніше. Це працює для цілочисельних індексів, але індекси на основі рядків не працюють.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.