Ратна (*Код 1009 * использует "HttpServerUtility.MapPath" для сопоставления виртуальных путей с физическим путем к файлу. Этот конкретный код очень хорошо работал для продукта. В нашей последней итерации мы заменяем HttpServerUtility.MapPath на HttpRequest.MapPath.
Под капотами HttpServerUtility.MapPath и HttpRequest.MapPath представляют собой один и тот же код и приведут к одному и тому же отображению. Оба эти метода проблематичны, когда речь идет о модульном тестировании.
Поиск "server.mappath null«Ссылка» в вашей любимой поисковой системе. Вы получите более 10 000 обращений. Почти все эти обращения вызваны тем, что тестовый код вызывает HttpContext.Current и HttpServerUtility.MapPath. Когда код ASP.NET выполняется без HTTP, HttpContext.Current будетбыть нулевым.
Эта проблема (HttpContext.Current is null) может быть очень легко решена с помощью crесть HttpWorkerRequest и инициализировать HttpContext.Current с этим.Вот код для этого -
string appPhysicalDir = @"c:\inetpub\wwwroot";
string appVirtualDir = "/";
SimpleWorkerRequest request = new SimpleWorkerRequest(appVirtualDir, appPhysicalDir, "/", null, new StringWriter());
HttpContext.Current = new HttpContext(request);
С помощью этого простого кода в модульном тесте HttpContext.Current инициализируется.Фактически, если вы заметили, HttpContext.Current.Server (HttpServerUtility) также будет отключен.Однако в тот момент, когда код пытается использовать Server.MapPath, будет выдано следующее исключение.
System.ArgumentNullException occurred
HResult=-2147467261
Message=Value cannot be null.
Parameter name: path
Source=mscorlib
ParamName=path
StackTrace:
at System.IO.Path.CheckInvalidPathChars(String path, Boolean checkAdditional)
InnerException:
HttpContext.Current = context;
Фактически, если код использует HttpContext.Current.Request.MapPath, он получиттакое же исключение.Если в коде используется Request.MapPath, проблема может быть легко решена в модульном тесте.Следующий код в модульном тестировании показывает, как.
string appPhysicalDir = @"c:\inetpub\wwwroot";
string appVirtualDir = "/";
SimpleWorkerRequest request = new SimpleWorkerRequest(appVirtualDir, appPhysicalDir, "/", null, new StringWriter());
FieldInfo fInfo = request.GetType().GetField("_hasRuntimeInfo", BindingFlags.Instance | BindingFlags.NonPublic);
fInfo.SetValue(request, true);
HttpContext.Current = new HttpContext(request);
В приведенном выше коде работающий с запросом сможет определить путь к карте.Однако этого недостаточно, потому что HttpRequest не имеет установленного HostingEnvironment (который разрешает MapPath).К сожалению, создание HostingEnvironment не является тривиальным.Таким образом, для модульного тестирования создается «фиктивный хост», который просто обеспечивает функциональность MapPath.Опять же, этот MockHost взламывает много внутреннего кода.Вот псевдокод для фиктивного хоста.Полный код можно скачать здесь: http://pastebin.com/ar05Ze7p
public MockHost(physicalDirectory, virtualDirectory){ ... }
public void Setup()
{
Create new HostingEnvironment
Set Call Context , mapping all sub directories as virtual directory
Initialize HttpRuntime's HostingEnvironment with the created one
}
С помощью приведенного выше кода, когда MapPath вызывается в HttpRequest, он должен иметь возможность разрешить путь.
В качестве последнего шага,в модульном тесте добавьте следующий код -
MockHost host = new MockHost(@"c:\inetpub\wwwroot\", "/");
host.Setup();
Так как теперь HostingEnvironment инициализирован, тестовый код сможет разрешать виртуальные пути при вызове метода HttpContext.Current.Request.MapPath (вместе сс HostingEnvironment.MapPath и HttpServerUtility.MapPath).
Загрузите код MockHost здесь: http://pastebin.com/ar05Ze7p