2011-08-09 8 views
7

I fijó esta sesión objeto de burla en el ejemplo aquí: How to MOQ an Indexed property¿Cómo puedo simular correctamente KeysCollection en HttpSessionStateBase?

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

algunos ejemplos de código para producir un error ...

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

error: El método u operación no está implementada.

Necesito implementar la propiedad Keys, pero no puedo crear un objeto KeysCollection.

¿Cuál es la mejor manera de hacerlo?

EDIT: [Solución]

acabé cambiando la HttpSessionMock en base a la respuesta dada. Esto es con lo que terminé. (También agregué una referencia a 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; } 
    } 
} 

nota: este simulacro de sesión se sólo cadenas de tiendas, no objetos.

+0

Aunque el código proviene de una pregunta de Moq, la solución no utiliza la biblioteca de Moq. Sugeriría eliminar la etiqueta Moq. – TrueWill

+0

Etiqueta Moq eliminada. – joelnet

+0

Este simulacro/falso explota cuando trato de meter un bool en él. Encontré un fragmento de código que funciona para esto aquí: http://stackoverflow.com/questions/524457/how-do-you-mock-the-session-object-collection-using-moq –

Respuesta

15

me encontré con una combinación del enfoque original y el solución aceptada permite tanto el almacenamiento de objetos como la implementación de la propiedad de claves:

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

Actualizado: Para su referencia, a continuación es el código fuente de KeysCollection del marco .NET:

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; 
     } 
    } 
} 
+0

objects.Keys is type Dictionary < TKey, TValue> .KeyCollection y HttpSessionStateBase es type NameObjectCollectionBase.KeysCollection, por lo tanto, no puedo asignarme a objects.Keys. – joelnet

+0

lo siento, no me di cuenta. sin embargo, puede heredar una nueva clase de NameObjectCollectionBase.KeysCollection, implementar su propia lógica, cuando se agrega un par de clave/valor a su diccionario, puede realizar los cambios necesarios en su KeysCollection. Espero que esto ayude. – gekowa

+0

También traté de heredar la clase, pero recibí este mensaje de error al crear mi propio constructor público "Error El tipo 'System.Collections.Specialized.NameObjectCollectionBase.KeysCollection' no tiene constructores definidos" – joelnet

4

Una manera:

internal sealed class HttpSessionMock : HttpSessionStateBase 
{ 
    public override NameObjectCollectionBase.KeysCollection Keys 
    { 
     get { return _collection.Keys; } 
    } 

    private readonly NameValueCollection _collection = new NameValueCollection(); 
} 
+0

Ahhh. Asi es como se hace. Gracias Señor. – joelnet

+1

Esto no funcionó para mí, la respuesta de scdove funcionó a la perfección. –

Cuestiones relacionadas