Как unit test код, который использует HostingEnvironment.MapPath

У меня есть код, который использует HostingEnvironment.MapPath, который я хотел бы unit test.

Как настроить HostingEnvironment так, чтобы он возвращал путь, а не null в мой проект unit test (mstest)?

Ответ 1

Почему у вас есть код, который зависит от HostingEnvironment.MapPath в приложении ASP.NET MVC, где у вас есть доступ к таким объектам, как HttpServerUtilityBase, которые позволяют вам достичь этого и которые можно легко издеваться и тестировать на модуле?

Возьмем пример: действие контроллера, которое использует абстрактный класс сервера, который мы хотим unit test:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var file = Server.MapPath("~/App_Data/foo.txt");
        return View((object)file);
    }
}

Теперь есть много способов unit test выполнить это действие контроллера. Лично мне нравится использовать MVcContrib.TestHelper.

Но посмотрим, как мы можем это сделать, используя насмешливую фреймворку из коробки. Я использую Rhino Mocks для этого примера:

[TestMethod]
public void Index_Action_Should_Calculate_And_Pass_The_Physical_Path_Of_Foo_As_View_Model()
{
    // arrange
    var sut = new HomeController();
    var server = MockRepository.GeneratePartialMock<HttpServerUtilityBase>();
    var context = MockRepository.GeneratePartialMock<HttpContextBase>();
    context.Expect(x => x.Server).Return(server);
    var expected = @"c:\work\App_Data\foo.txt";
    server.Expect(x => x.MapPath("~/App_Data/foo.txt")).Return(expected);
    var requestContext = new RequestContext(context, new RouteData());
    sut.ControllerContext = new ControllerContext(requestContext, sut);

    // act
    var actual = sut.Index();

    // assert
    var viewResult = actual as ViewResult;
    Assert.AreEqual(viewResult.Model, expected);
}

Ответ 2

Это будет зависеть от того, какую фальшивую или изолирующую структуру вы используете. Возможно, вы захотите заглянуть в: a) создание типа оболочки вокруг статического свойства, которое можно издеваться, или b) использование фреймворка, который может имитировать статические свойства - например, Moles или Typemock Isolator

Ответ 3

Ну, я сегодня пишу тест для кода, который я не контролирую, и они использовали

    private static String GetApplicationPath()
    {
        return HostingEnvironment.ApplicationVirtualPath.TrimEnd('/');
    }

так что здесь рассмотрим взлом С#, чтобы установить это значение

var path =  "/aaaa/bb";

HostingEnvironment hostingEnvironment;
if (HostingEnvironment.IsHosted.isFalse())
    new HostingEnvironment();

hostingEnvironment = (HostingEnvironment)typeof(HostingEnvironment).fieldValue("_theHostingEnvironment");

var virtualPath = "System.Web".assembly()
                   .type("VirtualPath").ctor();

virtualPath.field("_virtualPath", path);
//return virtualPath.prop("VirtualPathString");                
//return virtualPath.prop("VirtualPathStringNoTrailingSlash");                 

hostingEnvironment.field("_appVirtualPath", virtualPath);
//hostingEnvironment.field("_appVirtualPath") == virtualPath;

return HostingEnvironment.ApplicationVirtualPath == path;       

//using  System.Web.Hosting

Ответ 4

Просто используйте этот код.

Создайте новое имя папки. Ссылка в корневом каталоге и добавьте файл в эту папку.

Используйте этот

public static XElement GetFile()
{
    HttpContext.Current = new HttpContext(new HttpRequest("", "http://www.google.com", ""), new HttpResponse(new StringWriter()));

    var doc = new XmlDocument();
    var file = HttpContext.Current.Server.MapPath("\\") + "abc.xml";
    doc.Load(file);
    var e = XElement.Load(new XmlNodeReader(doc));
    return e;
}