tests - unit test moq c#
Burlándose de una sesión de NHibernate con Moq (2)
Estoy comenzando un nuevo proyecto con NHibernate, ASP.NET MVC 2.0 y StructureMap y estoy usando NUnit y Moq para las pruebas. Para cada uno de mis controladores tengo un único constructor público en el que se está inyectando una ISession. La aplicación en sí funciona bien, pero en términos de pruebas unitarias, esencialmente tengo que burlarme de una sesión para poder probar los controladores.
Cuando intento simular el ISession con MOQ, aparece el siguiente mensaje de error:
Solo se admiten accesos de propiedad en invocaciones intermedias.
Parece que mi problema está esperando la Lista de usuarios del método Framework CreateQuery pero, después de buscar en Google el problema, ahora estoy más claro.
Tengo dos preguntas:
1) ¿Es esta la manera INCORRECTA de simular la inyección de dependencia de una ISession?
2) ¿Hay alguna forma de modificar el código para que pueda devolver mi lista con éxito?
[Test]
public void DummyTest()
{
var mock = new Mock<ISession>();
var loc = new Mock<User>();
loc.SetupGet(x => x.ID).Returns(2);
loc.SetupGet(x => x.FirstName).Returns("John");
loc.SetupGet(x => x.LastName).Returns("Peterson");
var lst = new List<User> {loc.Object};
mock.Setup(framework => framework.CreateQuery("from User").List<User>()).Returns(lst);
var controller = new UsersController(mock.Object);
var result = controller.Index() as ViewResult;
Assert.IsNotNull(result.ViewData);
}
Tenga en cuenta que estoy bastante seguro de que podría crear una lista de usuarios codificada (en lugar de burlarse de un usuario individual y agregarla a una lista), pero pensé en dejar el código tal como lo tengo ahora.
Además, la acción de índice de este controlador en particular esencialmente ejecuta la llamada CreateQuery imitada anteriormente para devolver a todos los usuarios en la base de datos. Este es un ejemplo artificial: no lea nada en los detalles.
Gracias de antemano por tu ayuda
Edición: en respuesta al comentario a continuación, estoy agregando el stacktrace para el error. Además, todas las propiedades en la clase de usuario son virtuales.
TestCase ''Beta.Tests.Unit.Controllers.UserControllerTest.Details_InValidIndex_ReturnsNotFoundView'' falló: System.NotSupportedException: Solo se admiten accesos de propiedades en invocaciones intermedias en una configuración. Expresión no soportada framework.CreateQuery ("from User"). at Moq.Mock.AutoMockPropertiesVisitor.VisitMethod, Atall (MethodCallExpression m) en Moq.ExpressionVisitor.Visit (Expression exp) en Moq.Mock. .SetupMocks (Expresión de expresión) en Moq.Mock.GetInterceptor (LambdaExpression lambda, simulacro) en Moq.Mock. <> C__DisplayClass12
2.<Setup>b__11() at Moq.PexProtector.Invoke[T](Func
Función2.<Setup>b__11() at Moq.PexProtector.Invoke[T](Func
1) en Moq.Mock.Setup [T1, TResult] (simulacro de expresión1 expression) at Moq.Mock
1.Setup [TResult] (expresión `1 expresión) Controllers / UserControllerTest.cs (29,0): en Beta.Tests. Unit.Controllers.UserControllerTest.Details_InValidIndex_ReturnsNotFoundView ()
A continuación se muestra la solución que se me ocurrió, que parece funcionar perfectamente. Nuevamente, no estoy probando NHibernate y no estoy probando la base de datos, simplemente quiero probar los controladores que dependen de NHibernate. El problema con la solución inicial parece ser el hecho de que estaba llamando a un Método y leyendo el miembro de la Lista de la sesión en la llamada de configuración de MOQ. Rompí estas llamadas dividiendo la solución en un QueryMock y una sesión simulada (crear consulta devuelve un objeto IQuery). También fue necesario un simulacro de transacción, ya que es una dependencia (en mi caso) de la sesión ...
[Test]
public void DummyTest()
{
var userList = new List<User>() { new User() { ID = 2, FirstName = "John", LastName = "Peterson" } };
var sessionMock = new Mock<ISession>();
var queryMock = new Mock<IQuery>();
var transactionMock = new Mock<ITransaction>();
sessionMock.SetupGet(x => x.Transaction).Returns(transactionMock.Object);
sessionMock.Setup(session => session.CreateQuery("from User")).Returns(queryMock.Object);
queryMock.Setup(x => x.List<User>()).Returns(userList);
var controller = new UsersController(sessionMock.Object);
var result = controller.Index() as ViewResult;
Assert.IsNotNull(result.ViewData);
}
En lugar de burlarse de la Session
, uno podría considerar configurar una Configuration
diferente para las pruebas unitarias. Esta Configuration
prueba de unidad utiliza una base de datos en proceso rápida como SQLite o Firebird. En la configuración del aparato, crea una nueva base de datos de prueba completamente desde cero, ejecuta los scripts para configurar las tablas y crea un conjunto de registros iniciales. En la configuración por prueba, abre una transacción y en el desmontaje posterior a la prueba, se deshace de la transacción para restaurar la base de datos a su estado anterior. En cierto sentido, no te estás burlando de la Session
, porque eso se complica, pero te estás burlando de la base de datos real.