简体   繁体   English

如何最小起订量索引属性

[英]How to MOQ an Indexed property

I am attempting to mock a call to an indexed property.我试图模拟对索引属性的调用。 Ie I would like to moq the following:即我想最小起订量以下:

object result = myDictionaryCollection["SomeKeyValue"];

and also the setter value以及 setter 值

myDictionaryCollection["SomeKeyValue"] = myNewValue;

I am doing this because I need to mock the functionality of a class my app uses.我这样做是因为我需要模拟我的应用程序使用的类的功能。

Does anyone know how to do this with MOQ?有谁知道如何用 MOQ 做到这一点? I've tried variations on the following:我尝试了以下变体:

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

But that doesn't compile.但这不能编译。

Is what I am trying to achieve possible with MOQ, does anyone have any examples of how I can do this?我试图通过 MOQ 实现什么,有没有人有我如何做到这一点的例子?

It's not clear what you're trying to do because you don't show the declaration of the mock.不清楚您要做什么,因为您没有显示模拟的声明。 Are you trying to mock a dictionary?你是想嘲笑一本字典吗?

MyContainer[(string s)] isn't valid C#. MyContainer[(string s)]不是有效的 C#。

This compiles:这编译:

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

Ash, if you want to have HTTP Session mock, then this piece of code does the job: Ash,如果你想模拟 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);
    }
}

As you correctly spotted, there are distinct methods SetupGet and SetupSet to initialize getters and setters respectively.正如您正确发现的,有不同的方法SetupGetSetupSet分别初始化 getter 和 setter。 Although SetupGet is intended to be used for properties, not indexers, and will not allow you handling key passed to it.尽管SetupGet旨在用于属性,而不是索引器,并且不允许您处理传递给它的键。 To be precise, for indexers SetupGet will call Setup anyway:准确地说,对于索引器, 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);
    ...
  }
  ...
}

To answer your question, here is a code sample using underlying Dictionary to store values:为了回答您的问题,以下是使用底层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);

As you can see, you have to explicitly specify key to set up indexer setter.如您所见,您必须明确指定键来设置索引器设置器。 Details are described in another SO question: Moq an indexed property and use the index value in the return/callback详细信息在另一个 SO 问题中描述: Moq an indexed property and use the index value in the return/callback

Its not that difficult but it took a little bit to find it :)它不是那么难,但花了一点时间才找到它:)

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

It appears that what I was attempting to do with MOQ is not possible.看来我试图用 MOQ 做的事情是不可能的。

Essentially I was attempting to MOQ a HTTPSession type object, where the key of the item being set to the index could only be determined at runtime.本质上,我试图对 HTTPSession 类型的对象进行 MOQ,其中设置为索引的项的键只能在运行时确定。 Access to the indexed property needed to return the value which was previously set.访问需要返回先前设置的值的索引属性。 This works for integer based indexes, but string based indexes do not work.这适用于基于整数的索引,但基于字符串的索引不起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM