如何使用 VirtualPathUtility.GetAbsolute 方法在单元测试代码时模拟上下文

发布于 2024-12-06 19:45:20 字数 3124 浏览 4 评论 0原文

我正在对使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

知足的幸福 2024-12-13 19:45:20

我只想创建一个包装器接口。比如:

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

你可以将其注入到你的控制器中。在测试时,使用存根。在运行时,您将拥有一个实现 IPathUtilities 并调用 VirtualPathUtility.ToAbsolute() 的类。

I would just create a wrapper interface. Something like:

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

You can inject that into your controller. At test time, use a stub. At runtime, you'll have a class that implements IPathUtilities and calls VirtualPathUtility.ToAbsolute().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文