c# - una - variable de la sesión de burla en la prueba unitaria usando Moles
utilice la palabra new para crear una instancia de objeto c# (1)
Método que estoy probando en unidades verifica una variable de sesión como
if(Session["somevar"] != null)
{
// rest of the code
}
En mi prueba, no puedo deshacerme de esto porque la Session
es nula, está lanzando una excepción de referencia nula.
Para eludir esto, he intentado burlarlo como a continuación, pero sin suerte
System.Web.Moles.MHttpContext.AllInstances.SessionGet = (HttpContext cntx) =>
{ return (HttpSessionState)cntx.Session["somevar"]; }
Incluso intenté mencionar el método aquí para simular HttpContext y luego hacer abajo
HttpContext.Current = new HttpContext(workerRequest);
HttpContext.Current.Session["somevar"] = value;
Pero de nuevo no hubo suerte. Esta vez, aunque HttpContext.Current
no es nulo, pero HttpContext.Current.Session
y, por lo tanto, arroja una excepción de ref nula.
Alguna idea de cómo puedo simular esto / pasarlo en mi prueba [Sin usar ningún DLL externo o cambio de código principal. Lo siento, pero no puedo darme el lujo de hacerlo].
Gracias y mucho su ayuda.
Actualización 2013:
La mala noticia ahora es que el framework Moles fue un proyecto de Microsoft Research (MSR) y no será compatible con Visual Studio 2012 . La gran noticia es que Microsoft ahora ha integrado el proyecto MSR en el marco principal como Microsoft Fakes .
Encontré un artículo que resuelve el problema que tenías, usando el framework Fakes en lugar del framework Moles:
http://blog.christopheargento.net/2013/02/02/testing-untestable-code-thanks-to-ms-fakes/
Aquí hay una versión actualizada de mi respuesta anterior que usa el marco Fakes en lugar de Moles.
using System.Web.Fakes;
// ...
var sessionState = new Dictionary<string, object>();
ShimHttpContext.CurrentGet = () => new ShimHttpContext();
ShimHttpContext.AllInstances.SessionGet = (o) => new ShimHttpSessionState
{
ItemGetString = (key) =>
{
object result = null;
sessionState.TryGetValue(key, out result);
return result;
}
};
Incluso podrías hacer que se parezca más a la versión de Moles que publiqué antes, aunque todavía no lo he intentado. Solo estoy adaptando el código del artículo a mi respuesta :)
Antes de 2013 editar:
Dijiste que quieres evitar cambiar el código bajo prueba. Aunque creo que debería cambiarse, ya que acceder directamente al estado de sesión de esa manera es una mala idea, puedo entender de dónde vienes (estuve en prueba una vez ...).
Su código terminó luciendo así:
MHttpContext.CurrentGet = () => new MHttpContext
{
SessionGet = () => new MHttpSessionState
{
ItemGetString = (key) =>
{
if (key == "some")
return "someString"/* or any other object*/;
else return null;
}
}
};
Iría aún más lejos e implementaría ItemGetString
con un diccionario:
var sessionState = new Dictionary<string, object>();
MHttpContext.CurrentGet = // ...
{
// ...
ItemGetString = (key) =>
{
object result = null;
sessionState.TryGetValue(key, out result);
return result;
}
Antes de editar:
Normalmente resuelvo problemas como este al encapsular el estado global con una clase o interfaz abstracta que puede ser instanciada y burlada. Entonces, en lugar de acceder directamente al estado global, inyecto una instancia de mi clase o interfaz abstracta en el código que la usa.
Esto me permite simular el comportamiento global, y lo hace para que mis pruebas no dependan ni ejerzan ese comportamiento no relacionado.
Aquí hay una manera de hacerlo (jugaría con el factoring un poco):
public interface ISessionContext
{
object this[string propertyName] { get; set; }
}
public class ServerContext : ISessionContext
{
public object this[string propertyName]
{
get { return HttpContext.Current.Session[propertyName]; }
set { HttpContext.Current.Session[propertyName] = value; }
}
}
public class SomeClassThatUsesSessionState
{
private readonly ISessionContext sessionContext;
public SomeClassThatUsesSessionState(ISessionContext sessionContext)
{
this.sessionContext = sessionContext;
}
public void SomeMethodThatUsesSessionState()
{
string somevar = (string)sessionContext["somevar"];
// todo: do something with somevar
}
}
Esto requeriría cambios en su código bajo prueba, pero es el tipo de cambio que es bueno tanto para la capacidad de prueba como para la portabilidad del código.