如何使用 VirtualPathUtility.GetAbsolute 方法在单元测试代码时模拟上下文
我正在对使用 VirtualParthUtility.GetAbsolute 的代码运行单元测试,但在模拟上下文以使其工作时遇到问题。
我已经使用 Moq 设置了一个模拟上下文,如下所示
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;
}
并将其附加到 MVC 控制器
_myController.ControllerContext = new ControllerContext(MakeMockHttpContext("~/").Object, new RouteData(), _slideSelectorController);
测试期间运行的代码达到了目标:
venue.StyleSheetUrl = VirtualPathUtility.ToAbsolute(venue.StyleSheetUrl); // input like "~/styles/screen.css"
每次运行时,它都会进入 System.Web.VirtualPathUtility,问题是“ VirtualParthString”返回总是抛出异常:
public static string ToAbsolute(string virtualPath)
{
return VirtualPath.CreateNonRelative(virtualPath).VirtualPathString;
}
异常的原因很容易在 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;
}
}
通过监视窗口我可以看到 _virtualPath 和HttpRuntime.AppDomainAppVirtualPathString 均为 null,因此会引发异常。
如果设置了_virtualPath,则不会发生异常。但 VirtualPath.Create 方法创建新的 VirtualPath 对象后,在返回之前不会设置 _virtualPath 属性。到目前为止,Create 方法的摘录是:
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;
因此,如果有人可以建议如何让这个单元测试工作,那将非常有帮助!
谢谢,
史蒂夫
I am running unit tests on code which uses VirtualParthUtility.GetAbsolute, but am having problems mocking the context for this to work.
I've set up a mock context 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 attached this to an MVC Controller
_myController.ControllerContext = new ControllerContext(MakeMockHttpContext("~/").Object, new RouteData(), _slideSelectorController);
The code that runs during the test hits the line:
venue.StyleSheetUrl = VirtualPathUtility.ToAbsolute(venue.StyleSheetUrl); // input like "~/styles/screen.css"
Every time this runs, it steps into System.Web.VirtualPathUtility, with the problem that the "VirtualParthString" to be returned 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 Watch Window I can see that _virtualPath and HttpRuntime.AppDomainAppVirtualPathString are both null, hence it throws an exception.
If _virtualPath were set, the exception wouldn't happen. But after the VirtualPath.Create method has created a new VirtualPath object, it doesn't set the _virtualPath property before it is returned. An extract from the Create method up to this point is:
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 get this unit test working, that will be very helpful!
Thanks,
Steve
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我只想创建一个包装器接口。比如:
你可以将其注入到你的控制器中。在测试时,使用存根。在运行时,您将拥有一个实现 IPathUtilities 并调用 VirtualPathUtility.ToAbsolute() 的类。
I would just create a wrapper interface. Something like:
You can inject that into your controller. At test time, use a stub. At runtime, you'll have a class that implements
IPathUtilities
and callsVirtualPathUtility.ToAbsolute()
.