如何对使用HostingEnvironment.MapPath的代码进行单元测试

24

我有一些使用HostingEnvironment.MapPath的代码,希望进行单元测试。

如何设置HostingEnvironment,使其在我的单元测试(mstest)项目中返回一个路径而不是null


为什么在ASP.NET MVC应用程序中会有依赖于HostingEnvironment.MapPath的代码呢?在这种情况下,您可以访问像HttpServerUtilityBase这样的对象,它们允许您实现此目的,并且可以轻松地进行模拟和单元测试。也许您可以展示一下这段代码并解释一下场景,以便我们可以改进它? - Darin Dimitrov
4
因为我不知道 HttpServerUtilityBase。你能加个例子吗? - jgauffin
5个回答

14

为什么在ASP.NET MVC应用程序中有访问HttpServerUtilityBase等对象的情况下,您会有一个依赖于HostingEnvironment.MapPath的代码呢?这些对象可以帮助您实现此目标,并且可以轻松地进行模拟和单元测试。

让我们来看一个例子:一个控制器操作使用抽象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);
}

10
如果我们正在测试一个“ApiController”而不是“MVC”的一个,该怎么办? - A-Sharabiani
4
如果我们不是在测试控制器而是在测试实用类,该怎么办? - Dinh Tran
如果你正在测试不是你自己的代码,并且想要根据不存在的测试进行重构,该怎么办? - Eugenio Miró

4

我今天在为一段代码写测试,但这段代码并非由我控制,他们使用了

    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

0

这将取决于您使用的模拟或隔离框架。您可能需要考虑以下两种方法之一:a)创建一个包装器类型,用于封装可以进行模拟的静态属性;或者b)使用可以模拟静态属性的框架,例如MolesTypemock Isolator


0

由于我遇到了相同的问题,所以我稍微改变了我的代码。 来自

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());

-4

只需使用此代码...

在根目录中创建一个名为 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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接