Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test code that uses HostingEnvironment.MapPath

Tags:

I have some code that uses HostingEnvironment.MapPath which I would like to unit test.

How can I setup HostingEnvironment so that it returns a path and not null in my unit test (mstest) project?

like image 455
jgauffin Avatar asked Jan 05 '12 09:01

jgauffin


2 Answers

Why would you have a code that depends on HostingEnvironment.MapPath in an ASP.NET MVC application where you have access to objects like HttpServerUtilityBase which allow you to achieve this and which can be easily mocked and unit tested?

Let's take an example: a controller action which uses the abstract Server class that we want to unit test:

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

Now, there are many ways to unit test this controller action. Personally I like using the MVcContrib.TestHelper.

But let's see how we can do this using a mocking framework out-of-the-box. I use Rhino Mocks for this example:

[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); } 
like image 76
Darin Dimitrov Avatar answered Oct 21 '22 13:10

Darin Dimitrov


Well I was writing a test today for code that I don't control and they used

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

so here is a C# reflection hack to set that value

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 
like image 31
Dinis Cruz Avatar answered Oct 21 '22 12:10

Dinis Cruz