How to spoof a context during unit testing using the VirtualPathUtility.GetAbsolute method

I run unit tests of code that uses VirtualParthUtility.GetAbsolute, but I am having trouble mocking the context for this.

I set the layout with Moq as follows

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; } 

And tied it to the MVC controller

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

The code that runs during the test falls into the line:

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

Each time this is executed, it goes to System.Web.VirtualPathUtility, with the problem that the returned "VirtualParthString" always throws an exception:

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

The reason for the exception is easy to see in 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; } } 

Through the viewport, I see that _virtualPath and HttpRuntime.AppDomainAppVirtualPathString are zero, so it throws an exception.

If _virtualPath is set, an exception will not occur. But after the VirtualPath.Create method has created a new VirtualPath object, it does not set the _virtualPath property until it is returned. Excerpt from Create method up to this point:

 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; 

So, if anyone can suggest how to do a unit test, this will be very helpful!

Thanks,

Steve

+6
source share
1 answer

I would just create a shell interface. Sort of:

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

You can enter this in your controller. Use a dummy during testing. At run time, you will have a class that implements IPathUtilities and calls VirtualPathUtility.ToAbsolute() .

+5
source

Source: https://habr.com/ru/post/897967/


All Articles