【问题标题】:How to mock context while unit testing code using VirtualPathUtility.GetAbsolute method如何在使用 VirtualPathUtility.GetAbsolute 方法对代码进行单元测试时模拟上下文
【发布时间】:2011-09-24 12:11:58
【问题描述】:

我正在对使用 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;

所以,如果有人能建议如何让这个单元测试工作,那将非常有帮助!

谢谢,

史蒂夫

【问题讨论】:

  • 看了一下,也许我需要使用隔离框架来模拟静态方法HttpRuntime.AppDomainAppVirtualPath?

标签: unit-testing model-view-controller mocking moq


【解决方案1】:

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

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

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

【讨论】:

  • 感谢您的建议。不错的优雅解决方案。
  • 存根是什么意思?
猜你喜欢
  • 2015-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多