2011-09-24 9 views
6

Estoy ejecutando pruebas unitarias en el código que usa VirtualParthUtility.GetAbsolute, pero tengo problemas para burlar el contexto para que esto funcione.Cómo simular el contexto mientras el código de prueba de la unidad utiliza el método VirtualPathUtility.GetAbsolute

He creado un contexto maqueta con Moq de la siguiente manera

private Mock<HttpContextBase> MakeMockHttpContext(string url) // url = "~/" 
    { 
     var mockHttpContext = new Mock<HttpContextBase>(); 

     // Mock the request 
     var mockRequest = new Mock<HttpRequestBase>(); 
     mockRequest.Setup(x => x.ApplicationPath).Returns("/"); 
     mockRequest.Setup(x => x.Path).Returns("/"); 
     mockRequest.Setup(x => x.PathInfo).Returns(string.Empty); 
     mockRequest.Setup(x => x.AppRelativeCurrentExecutionFilePath).Returns(url); 

     mockHttpContext.Setup(x => x.Request).Returns(mockRequest.Object); 

     // Mock the response 
     var mockResponse = new Mock<HttpResponseBase>(); 
     mockResponse.Setup(x => x.ApplyAppPathModifier(It.IsAny<string>())).Returns((string s) => s); 

     mockHttpContext.Setup(x => x.Response).Returns(mockResponse.Object); 

     return mockHttpContext; 
    } 

y unido esto a un controlador MVC

_myController.ControllerContext = new ControllerContext(MakeMockHttpContext("~/").Object, new RouteData(), _slideSelectorController); 

El código que se ejecuta durante la prueba golpea la línea:

venue.StyleSheetUrl = VirtualPathUtility.ToAbsolute(venue.StyleSheetUrl); // input like "~/styles/screen.css" 

Cada vez que esto se ejecuta, entra en System.Web.VirtualPathUtility, con el problema de que el "VirtualP arthString" para ser devuelto siempre se produce una excepción:

public static string ToAbsolute(string virtualPath) 
{ 
    return VirtualPath.CreateNonRelative(virtualPath).VirtualPathString; 
} 

La razón de la excepción es fácil de ver en System.Web.VirtualPathString:

public string VirtualPathString 
{ 
    get 
    { 
    if (this._virtualPath == null) 
    { 
     if (HttpRuntime.AppDomainAppVirtualPathObject == null) 
     { 
     throw new HttpException(System.Web.SR.GetString("VirtualPath_CantMakeAppAbsolute", new object[] { this._appRelativeVirtualPath })); 
     } 
     if (this._appRelativeVirtualPath.Length == 1) 
     { 
     this._virtualPath = HttpRuntime.AppDomainAppVirtualPath; 
     } 
     else 
     { 
     this._virtualPath = HttpRuntime.AppDomainAppVirtualPathString + this._appRelativeVirtualPath.Substring(2); 
     } 
    } 
    return this._virtualPath; 
    } 
} 

A través de la ventana de visualización puedo ver que _virtualPath y HttpRuntime.AppDomainAppVirtualPathString son ambos nulos, por lo tanto arroja una excepción.

Si se estableció _virtualPath, la excepción no ocurrirá. Pero después de que el método VirtualPath.Create haya creado un nuevo objeto VirtualPath, no establece la propiedad _virtualPath antes de que se devuelva. Un extracto del método Create hasta este punto es:

VirtualPath path = new VirtualPath(); 
    if (UrlPath.IsAppRelativePath(virtualPath)) 
    { 
    virtualPath = UrlPath.ReduceVirtualPath(virtualPath); 
    if (virtualPath[0] == '~') 
    { 
     if ((options & VirtualPathOptions.AllowAppRelativePath) == 0) 
     { 
     throw new ArgumentException(System.Web.SR.GetString("VirtualPath_AllowAppRelativePath", new object[] { virtualPath })); 
     } 
     path._appRelativeVirtualPath = virtualPath; 
     return path; 

Así que si alguien puede sugerir cómo conseguir este trabajo de prueba de unidad, que será muy útil!

Gracias,

Steve

+0

Leyendo, tal vez necesito usar un Framework de Aislamiento para simular el método estático HttpRuntime.AppDomainAppVirtualPath? – Appetere

Respuesta

5

me acaba de crear una interfaz de contenedor. Algo como:

public interface IPathUtilities 
{ 
    string ToAbsolute(string virtualPath); 
} 

Puede inyectar eso en su controlador. En el momento de la prueba, use un stub. En tiempo de ejecución, tendrá una clase que implementa IPathUtilities y llama al VirtualPathUtility.ToAbsolute().

+0

Gracias por la sugerencia. Buena y elegante solución. – Appetere

+0

Si te gusta esta respuesta, márcala como la solución aceptada. ¡Gracias! – PatrickSteele

Cuestiones relacionadas