2009-12-30 17 views
14

¿Existe alguna manera de simular/falsificar el objeto de sesión en los formularios web ASP.Net al crear pruebas unitarias?¿Cómo puedo simular/simular el objeto de sesión en los formularios web de ASP.Net?

Actualmente estoy almacenando detalles de usuario en una variable de sesión a la que accedo mi lógica comercial.

Al probar mi lógica comercial de forma aislada, la sesión no está disponible. Esto parece indicar un mal diseño (aunque no estoy seguro). ¿Debería la capa de lógica de negocios acceder a las variables de sesión en primer lugar?

Si es así, ¿cómo voy a intercambiar los detalles del usuario con un objeto falso para probar?

+0

Véase también mi respuesta a esta pregunta - http://stackoverflow.com/a/8487847/232593 –

Respuesta

9

En ASP.NET, no puede crear una prueba doble de HttpSessionState porque es sealed. Sí, este es un mal diseño por parte de los diseñadores originales de ASP.NET, pero no hay mucho que hacer al respecto.

Esta es una de las muchas razones por las cuales los TDD'ers y otros profesionales de SOLID han abandonado ASP.NET en gran medida a favor de ASP.NET MVC y otros marcos más comprobables. En ASP.NET MVC, la sesión HTTP se modela mediante la clase abstracta HttpSessionStateBase.

Puede adoptar un enfoque similar y dejar que sus objetos funcionen en una sesión abstracta, y luego ajustar la clase HttpSessionState real cuando se está ejecutando en el entorno ASP.NET. Dependiendo de las circunstancias, incluso puede reutilizar los tipos de System.Web.Abstractions, pero si no, puede definir los suyos propios.

En cualquier caso, su lógica de negocio es su Dominio Modelo y debe modelarse independientemente de cualquier tecnología de tiempo de ejecución particular, por lo que diría que no debería estar accediendo al objeto de sesión en primer lugar.

Si es absolutamente necesario utilizar la prueba de dobles para tets de la unidad implican HttpSessionState, esto sigue siendo posible con ciertas dinámicas burla invasivos, tales como TypeMock o Moles, aunque incluya estos llevan un montón de desventajas también (ver this comparison of dynamic mocks).

1

Sus instintos son correctos --- no debe acceder a elementos de la infraestructura de ASP.NET desde su lógica de negocio. Esto incluiría la Sesión.

para responder a su primera pregunta, usted puede clases estáticas simulados utilizando un producto como Typemock aislador, pero será mejor si refactorizar el código para envolver el acceso a la sesión en una interfaz (es decir, IHttpSession). Luego puede burlarse de IHttpSession.

0

Un enfoque es pasar una expresión lambda a su código que toma una cadena (u otro objeto) como entrada, y la usa para establecer el objeto Session o un contenedor de prueba.

Sin embargo, como han dicho otros, es una buena idea mover el acceso al objeto de sesión fuera de su BLL.

1

En los formularios web Asp.Net, no puede evitar el hecho de que la entrada de framework en su código proviene de páginas aspx. Estoy de acuerdo en que su capa de negocios no debe tocar los componentes específicos de asp.net directamente, pero debe tener el contenedor de almacenamiento de un modelo y la sesión en asp.net es una buena área. Por lo tanto, un posible enfoque es crear ISessionManager con el propósito de interactuar dentro de la capa de su empresa. Luego, implemente el tipo concreto usando HttpSessionState ... btw, un buen truco es usar HttpContext.Current.Session para implementar accesors/getters fuera del HttpSessionState. Su próximo desafío sería cómo conectarlo todo junto.

25

Puede hacerlo básicamente con 4 líneas de código. Aunque esto no refleja el comentario anterior de mover la sesión fuera de la capa de lógica de negocios, a veces es posible que deba hacer esto de todos modos si está trabajando con un código heredado que está fuertemente acoplado a la sesión (mi escenario).

Los espacios de nombres:

using System.Web; 
using System.IO; 
using System.Web.Hosting; 
using System.Web.SessionState; 

El código:

HttpWorkerRequest _wr = new SimpleWorkerRequest(
    "/dummyWorkerRequest", @"c:\inetpub\wwwroot\dummy", 
    "default.aspx", null, new StringWriter()); 

HttpContext.Current = new HttpContext(_wr); 

var sessionContainer = new HttpSessionStateContainer(
    "id", new SessionStateItemCollection(), 
    new HttpStaticObjectsCollection(), 10, true, 
    HttpCookieMode.AutoDetect, SessionStateMode.InProc, false); 

SessionStateUtility.AddHttpSessionStateToContext(
    HttpContext.Current, sessionContainer); 

A continuación, puede referirse a la sesión sin conseguir un error NullReferenceException:

HttpContext.Current.Session.Add("mySessionKey", 1); 

Esta es una combinación de código Recopilé de los artículos a continuación:

+0

Excelente, gracias. –

+0

Gracias, buen trabajo – Manish

+0

Estoy recibiendo la excepción de ViewEngine al llamar al método de índice de la clase de prueba de la unidad. ¿Hay alguna solución para lo mismo? – Manish

Cuestiones relacionadas