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

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

Как я могу настроить HostingEnvironment так что он возвращает путь, а не null в моем модульном тесте (mstest) проекта?

4 ответа

Решение

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

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

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

Теперь есть много способов модульного тестирования этого действия контроллера. Лично мне нравится использовать 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);
}

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

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

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

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

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

Когда я столкнулся с той же проблемой, я изменил свой бит кода.Из

strhtmlTemplate = File.ReadAllText(System.Web.Hosting.HostingEnvironment.MapPath(Lgetfilepath.CVal));

Чтобы

strhtmlTemplate = File.ReadAllText(HttpContextFactory.Current.Server.MapPath(Lgetfilepath.CVal));

Для модульного теста

public HttpContextBase mockHttpContextBase()
        {
            var moqContext = new Mock<HttpContextBase>();
            var moqRequest = new Mock<HttpRequestBase>();
            var moqServer = new Mock<HttpServerUtilityBase>();
            var moqPath = new Mock<ConfigurationBase>();
            moqContext.Setup(x => x.Request).Returns(moqRequest.Object);
            moqContext.Setup(x => x.Server.MapPath(@"~\Data\xxxxxxx")).Returns(Environment.CurrentDirectory+@"\xxxxxx");                
            setupApplication(moqContext);

            return moqContext.Object;
        }

Теперь, когда мы пишем TestClass, вам нужно сослаться на вышеуказанный метод для имитации. Надеюсь, это будет полезно для ваших тестов.

MockDataUT mockData = new MockDataUT();
var mockRequestContext = new HttpRequestContext();
HttpContextFactory.SetCurrentContext(mockData.mockHttpContextBase());

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

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

Использовать этот

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;
}
Другие вопросы по тегам