Как смоделировать контекст во время модульного тестирования кода с использованием метода VirtualPathUtility.GetAbsolute - PullRequest
6 голосов
/ 24 сентября 2011

Я запускаю модульные тесты для кода, который использует 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;

Так что если кто-нибудь может подсказать, как заставить работать этот модульный тест, это будет очень полезно!

Спасибо

Steve

1 Ответ

5 голосов
/ 27 сентября 2011

Я бы просто создал интерфейс-обертку. Что-то вроде:

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

Вы можете добавить это в свой контроллер. Во время теста используйте заглушку. Во время выполнения у вас будет класс, который реализует IPathUtilities и вызывает VirtualPathUtility.ToAbsolute().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...