Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to MapPath in a unit test in C#

Tags:

c#

I want to load an external XML file in a unit test to test some processing code on that XML. How do I get the path of the file?

Usually in a web app I would do:

XDocument.Load(Server.MapPath("/myFile.xml"));

But obviously in my unit test I have no reference to Server or HttpContext so how can I map a path so that I don't have to specify the full path?

UPDATE:

I just want to make it clear that the code I'm actually testing is for an XML parser class, something like:

public static class CustomerXmlParser {
  public static Customer ParseXml(XDocument xdoc) {
    //...
  }
}

So to test this I need to parse a valid XDocument. The method being tested does not access the file system itself. I could create the XDocument from a String directly in the test code but I thought it would be easier to just load it from a file.

like image 656
David Glenn Avatar asked Aug 05 '09 08:08

David Glenn


3 Answers

Another idea would be to utilize dependency injection.

public interface IPathMapper {
string MapPath(string relativePath);
}

And then simply use 2 implementations

public class ServerPathMapper : IPathMapper {
     public string MapPath(string relativePath){
          return HttpContext.Current.Server.MapPath(relativePath);
     }
}

And then you also need your mock implementation

public class DummyPathMapper : IPathMapper {
    public string MapPath(string relativePath){
        return "C:/Basedir/" + relativePath;
    }
}

And then all your functions that needs to map path's would simply need to have access to an instance of IPathMapper - in your web app it needs to be the ServerPathMapper and in your unit tests the DummyPathMapper - basic DI (Dependency Injection).

like image 109
kastermester Avatar answered Nov 10 '22 11:11

kastermester


Usually for unit tests I add the xml files as embedded resources to the project and load them using a method like this:

public static string LoadResource(string name)
{
  Type thisType = MethodBase.GetCurrentMethod().DeclaringType;
  string fullName = thisType.Namespace + "." + name + ".xml";

  using (Stream stream = thisType.Module.Assembly.GetManifestResourceStream(fullName))
  {
      if(stream==null)
      {
        throw new ArgumentException("Resource "+name+" not found.");
      }

      StreamReader sr = new StreamReader(stream);
      return sr.ReadToEnd();
  }
}
like image 21
Grzenio Avatar answered Nov 10 '22 11:11

Grzenio


Personally, I'd be very wary about having any code that relies on a back-end resource store, be that a file system or a database - you are introducing a dependency into your unit test that is likely to lead to false negatives i.e tests failing not because of your specific test code but because the file isn't there or the server is unavailable etc.
See this link for IMO a good definition of what a unit test is and more importantly is not

Your unit test should be testing an atomic, well-defined piece of functionality not testing whether a file can load. One solution is to 'mock' the file load - there are various approaches to this however, I'd personally only mock the interface to the file system your are using and not try and do any full filesystem mocking - here's a good SO post and here's a good SO discussion on file system mocking

Hope that helps

like image 45
zebrabox Avatar answered Nov 10 '22 12:11

zebrabox