2011-05-17 14 views
5

Estoy intentando crear pruebas de integración para asegurarme de que mis vistas no tengan ningún error en el tiempo de ejecución. Por lo tanto, necesito crear una prueba que compruebe si el ViewResult.ExecuteResult() funciona correctamente, pero parece que me he topado con un problema.¿Cómo puedo simular correctamente mi controladorcontexto para probar ViewResult.ExecuteResult()?

me encontré this site que me dio un punto de partida, y tengo el siguiente código:

[TestMethod] 
    public void RegisterResultExecutes() 
    { 
     //arrange 
     RequestContext requestContext = new RequestContext(new MockHttpContext(), new RouteData()); 
     AccountController controller = new AccountController 
     { 
      FormsService = new MockFormsAuthenticationService(), 
      MembershipService = new MockMembershipService(), 
      Url = new UrlHelper(requestContext) 
     }; 

     var result = controller.Register(); 
     var sb = new StringBuilder(); 
     Mock<HttpResponseBase> response = new Mock<HttpResponseBase>(); 
     response.Setup(x => x.Write(It.IsAny<string>())).Callback<string>(y => 
     { 
      sb.Append(y); 
     }); 
     Mock<ControllerContext> controllerContext = new Mock<ControllerContext>(); 
     controllerContext.Setup(x => x.HttpContext.Response).Returns(response.Object); 

     //act 
     result.ExecuteResult(controllerContext.Object); 
    } 

El problema es que cuando result.ExecuteResult() se llama consigo la siguiente excepción

System.NullReferenceException: Object reference not set to an instance of an object. 

System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) 
MyApp.Tests.Controllers.AccountControllerTest.RegisterResultExecutes() in C:\Users\KallDrexx\Documents\Projects\MyApp\MyApp.Tests\Controllers\AccountControllerTests.cs: line 297 

Por desgracia, ese rastro de pila no es muy útil ya que no estoy seguro de a qué intenta acceder que sea nulo. ¿Alguien tiene alguna sugerencia sobre cómo puedo crear una prueba para ExecuteResult()?

Respuesta

4

Según el seguimiento de la pila, es algo en el método ViewResultBase.ExecuteResult que arroja la excepción. El uso del reflector, aquí es la definición de ese método:

public override void ExecuteResult(ControllerContext context) 
{ 
    if (context == null) 
    { 
     throw new ArgumentNullException("context"); 
    } 
    if (string.IsNullOrEmpty(this.ViewName)) 
    { 
     this.ViewName = context.RouteData.GetRequiredString("action"); 
    } 
    ViewEngineResult result = null; 
    if (this.View == null) 
    { 
     result = this.FindView(context); 
     this.View = result.View; 
    } 
    TextWriter output = context.HttpContext.Response.Output; 
    ViewContext viewContext = new ViewContext(context, this.View, this.ViewData, this.TempData, output); 
    this.View.Render(viewContext, output); 
    if (result != null) 
    { 
     result.ViewEngine.ReleaseView(context, this.View); 
    } 
} 

Sobre la base de ese código, una excepción referencia de objeto podría ser lanzado cuando el código intenta acceder a la propiedad RouteData del contexto (si el nombre de la vista wasn dado explícitamente al tipo de devolución).

La excepción podría producirse al acceder a la propiedad HttpContext. No he usado Moq lo suficientemente bien como para saber si puede manejar el hecho de que no le ha dicho cómo burlarse de la propiedad HttpContext, pero le ha dicho cómo burlarse de la propiedad Response del tipo de propiedad HttpContext, por lo que es otra área que es sospechosa para mí.

Todos los demás usos del contexto en el método lo están pasando a otros métodos, que si ese fuera el problema, entonces el seguimiento de la pila lo habría revelado.

La manera más fácil de ver cuál de los dos mencioné es el problema, escribiría una prueba rápida para extraer esas propiedades de tus simulaciones y ver cuál causa la excepción.

+0

Aha, que la reflexión da una gran cantidad de información. Fue 'RouteData' lo que estaba causando el problema, pero ahora parece que necesito encontrar una forma para' context.RouteData.GetRequiredString ("action"); 'para devolver algo útil, ya que es donde estoy estancado ahora – KallDrexx

+0

Bien después de configurar 'RouteData' correctamente, parece que estoy al límite de lo que puedo hacer, y esto parece ser imposible. La llamada a 'FindView()' obtiene una 'NullReferenceException' 15 (literalmente) capas en el rastro de pila en' System.Web.Compilation.BuildManager.GetCacheKeyFromVirtualPath() '. Oh, bueno :( – KallDrexx

+0

Temía que te toparas con un tapón de show como ese. ¿Hay algo específico que estés tratando de probar en tus vistas? Si quieres asegurarte de que tus expresiones lambda estén bien (si estás usando alguna) puede [compilar sus puntos de vista] (http://stackoverflow.com/questions/383192/compile-views-in-asp-net-mvc). Si desea probar javascript, entonces buscaría en Google pruebas de la unidad de JavaScript como Sé que hay marcos para eso, pero no los he usado. ¿O está intentando probar algo más junto a todos juntos? –

1

Me tocó el mismo problema que ahora y lo resolvió configurando HttpContext.Current.

Intente agregar lo siguiente al código de prueba de su unidad: p. Ej.

HttpContext.Current = new HttpContext(
    new HttpRequest("", "http://mock", ""), 
    new HttpResponse(new StringWriter())); 

Una cosa que he encontrado útil para depurar este tipo de problemas en lugar de utilizar reflector o ILSpy es convertir en símbolos de depuración para el código de .NET Framework. De esta forma, puede conectarse a su proceso NUnit y ver exactamente qué línea de código arroja la excepción y, por lo tanto, qué necesita para simular en la prueba.

Shawn Burke ha escrito un excelente artículo de blog que detalla cómo configurar esta aquí: http://blogs.msdn.com/b/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx

+0

Oh limpio. Gracias por eso – KallDrexx

Cuestiones relacionadas