【问题标题】:How can I properly Mock the KeysCollection in HttpSessionStateBase?如何正确模拟 HttpSessionStateBase 中的 KeysCollection?
【发布时间】:2012-11-08 09:08:36
【问题描述】:

我在此处的示例中设置了这个模拟会话对象:How to MOQ an Indexed property

/// <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; }
    }
}

一些产生错误的示例代码...

var mockSession = new HttpSessionMock();
var keys = mockSession.Keys;

错误:方法或操作未实现。

我需要实现 Keys 属性,但无法创建 KeysCollection 对象。

最好的方法是什么?

编辑:[解决方案]

我最终根据给出的答案更改了 HttpSessionMock。这就是我最终的结果。 (我还添加了对 System.Linq 的引用)。

internal sealed class HttpSessionMock : HttpSessionStateBase
{
    private readonly NameValueCollection objects = new NameValueCollection();

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

    public override NameObjectCollectionBase.KeysCollection Keys
    {
        get { return objects.Keys; }
    }
}

注意:这个模拟会话将只存储字符串,而不是对象。

【问题讨论】:

  • 虽然代码来自一个 Moq 问题,但该解决方案不使用 Moq 库。我建议删除 Moq 标签。
  • 当我尝试在其中塞入一个 bool 时,这个 mock/fake 会爆炸。我在这里找到了适用于此的代码 sn-p:stackoverflow.com/questions/524457/…

标签: c# unit-testing asp.net-mvc-3 session


【解决方案1】:

我发现原始方法和公认解决方案的组合允许存储对象和实现 keys 属性:

public class HttpSessionMock : HttpSessionStateBase
{
    private readonly NameValueCollection keyCollection = new NameValueCollection();
    private readonly Dictionary<string, object> objects = new Dictionary<string, object>();

    public override object this[string name]
    {
        get
        {
            object result = null;

            if (objects.ContainsKey(name))
            {
                result = objects[name];
            }

            return result;

        }
        set
        {
            objects[name] = value;
            keyCollection[name] = null;
        }
    }

    public override NameObjectCollectionBase.KeysCollection Keys
    {
        get { return keyCollection.Keys; }
    }
}

【讨论】:

    【解决方案2】:

    一种方式:

    internal sealed class HttpSessionMock : HttpSessionStateBase
    {
        public override NameObjectCollectionBase.KeysCollection Keys
        {
            get { return _collection.Keys; }
        }
    
        private readonly NameValueCollection _collection = new NameValueCollection();
    }
    

    【讨论】:

      【解决方案3】:

      更新: 供您参考,下面是 .NET 框架中 KeysCollection 的源代码:

      public class KeysCollection : ICollection, IEnumerable
      {
          // Fields
          private NameObjectCollectionBase _coll;
      
          // Methods
          internal KeysCollection(NameObjectCollectionBase coll)
          {
              this._coll = coll;
          }
      
          public virtual string Get(int index)
          {
              return this._coll.BaseGetKey(index);
          }
      
          public IEnumerator GetEnumerator()
          {
              return new NameObjectCollectionBase.NameObjectKeysEnumerator(this._coll);
          }
      
          void ICollection.CopyTo(Array array, int index)
          {
              if (array == null)
              {
                  throw new ArgumentNullException("array");
              }
              if (array.Rank != 1)
              {
                  throw new ArgumentException(SR.GetString("Arg_MultiRank"));
              }
              if (index < 0)
              {
                  throw new ArgumentOutOfRangeException("index", SR.GetString("IndexOutOfRange", new object[] { index.ToString(CultureInfo.CurrentCulture) }));
              }
              if ((array.Length - index) < this._coll.Count)
              {
                  throw new ArgumentException(SR.GetString("Arg_InsufficientSpace"));
              }
              IEnumerator enumerator = this.GetEnumerator();
              while (enumerator.MoveNext())
              {
                  array.SetValue(enumerator.Current, index++);
              }
          }
      
          // Properties
          public int Count
          {
              get
              {
                  return this._coll.Count;
              }
          }
      
          public string this[int index]
          {
              get
              {
                  return this.Get(index);
              }
          }
      
          bool ICollection.IsSynchronized
          {
              get
              {
                  return false;
              }
          }
      
          object ICollection.SyncRoot
          {
              get
              {
                  return ((ICollection) this._coll).SyncRoot;
              }
          }
      }
      

      【讨论】:

      • objects.Keys 是 Dictionary.KeyCollection 类型,而 HttpSessionStateBase 是 NameObjectCollectionBase.KeysCollection 类型,所以我无法映射到 objects.Keys。
      • 抱歉没有注意到。但是,您可以从 NameObjectCollectionBase.KeysCollection 继承一个新类,实现您自己的逻辑,当一个键/值对添加到您的字典时,您可以对您的 KeysCollection 进行必要的更改。希望这会有所帮助。
      • 我也尝试继承该类,但在创建自己的公共构造函数时收到此错误消息“错误 1 ​​类型 'System.Collections.Specialized.NameObjectCollectionBase.KeysCollection' 没有定义构造函数”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-30
      • 2018-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-05
      相关资源
      最近更新 更多