Как MapPath в модульном тесте в C # - PullRequest
14 голосов
/ 05 августа 2009

Я хочу загрузить внешний XML-файл в модульном тесте, чтобы протестировать некоторый код обработки для этого XML. Как мне получить путь к файлу?

Обычно в веб-приложении я бы делал:

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

Но, очевидно, в моем модульном тесте у меня нет ссылки на Server или HttpContext, так как я могу сопоставить путь, чтобы мне не пришлось указывать полный путь?

UPDATE:

Я просто хочу прояснить, что код, который я на самом деле тестирую, предназначен для класса XML-анализатора, что-то вроде:

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

Итак, чтобы проверить это, мне нужно проанализировать действительный XDocument. Тестируемый метод не имеет доступа к самой файловой системе. Я мог создать XDocument из String непосредственно в тестовом коде, но я подумал, что было бы проще просто загрузить его из файла.

Ответы [ 6 ]

24 голосов
/ 05 августа 2009

Другая идея заключается в использовании внедрения зависимостей.

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

А затем просто используйте 2 реализации

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

И тогда вам также понадобится ваша фиктивная реализация

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

И тогда все ваши функции, которые должны отображать пути, просто должны иметь доступ к экземпляру IPathMapper - в вашем веб-приложении это должен быть ServerPathMapper, а в вашем модуле тестируется DummyPathMapper - базовый DI (Dependency Injection).

5 голосов
/ 05 августа 2009

Лично я бы очень настороженно относился к любому коду, использующему бэкэнд хранилище ресурсов, будь то файловая система или база данных - вы вводите в свой модульный тест зависимость, которая может привести к ложным отрицаниям, т.е. к сбоям тестов не из-за вашего конкретного кода теста, а из-за отсутствия файла или сервера недоступен и т. д.
Посмотрите эту ссылку для ИМО, хорошее определение того, что такое юнит-тест и, что более важно, не

Ваш модульный тест должен тестировать элементарный, четко определенный функционал, а не тестировать, может ли файл загружаться. Одно из решений состоит в том, чтобы «смоделировать» загрузку файла - однако существуют различные подходы к этому, однако, я бы лично смоделировал только интерфейс с используемой вами файловой системой, а не пытался выполнить какую-либо полную имитацию файловой системы - здесь хороший SO пост и вот хороший SO дискуссия о насмешках над файловой системой

Надеюсь, это поможет

3 голосов
/ 05 августа 2009

Обычно для модульных тестов я добавляю файлы xml в качестве встроенных ресурсов в проект и загружаю их, используя метод, подобный следующему:

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();
  }
}
2 голосов
/ 05 августа 2009

Редактировать: Я начинаю с нуля, так как, по-моему, я неправильно истолковал ваш вопрос.

Лучший способ загрузить файл XML в модульном тесте для последующего внедрения его в некоторые из ваших классов - это использовать атрибут DeploymentItem в модульных тестах MS.

Это будет выглядеть следующим образом:

[TestMethod]
[DeploymentItem(@"DataXmlFiles\MyTestFile.xml", "DataFiles")]
public void LoadXMLFileTest()
{
   //instead of "object" use your returning type (i.e. string, XDocument or whatever)
   //LoadXmlFile could be a method in the unit test that actually loads an XML file from the File system
   object myLoadedFile = LoadXmlFile(Path.Combine(TestContext.TestDeploymentDir, "DataFiles\\MyTestFile.xml"));

   //do some unit test assertions to verify the outcome
}

Я сейчас не тестировал код на отладчике, но он должен работать.

Edit: Кстати, когда вы используете DeploymentItem, рассмотрите этот пост здесь .

1 голос
/ 28 декабря 2013

Классы:

internal class FakeHttpContext : HttpContextBase
{
    public override HttpRequestBase Request { get { return new FakeHttpRequest(); } }
}

internal class FakeHttpRequest : HttpRequestBase
{
    public override string MapPath(string virtualPath)
    {
        return /* your mock */
    }
}

Использование:

[TestMethod]
public void TestMethod()
{
    var context = new FakeHttpContext();
    string pathToFile = context.Request.MapPath("~/static/all.js");
}
0 голосов
/ 26 ноября 2018

Это может быть полезно для кого-то. У меня была связанная проблема. Хотел использовать файл Excel из папки корневого уровня в моем проекте c # Unit Test.

У меня была корневая папка с именем «TestFiles». Внутри у меня был "Test.xlsx".

То, что я сделал, было:

Щелкните правой кнопкой мыши файл «Test.xlsx», перейдите в «Свойства» и установите «Копировать в каталог вывода» = «Копировать всегда»

Теперь файл и содержащая его папка «TestFiles» всегда копируются в папку bin проекта Unit Test. Чтобы я мог использовать его так:

var filePath = "TestFiles/Test.xlsx";
var strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=0\"";
using (var conn = new OleDbConnection(strConn))
{
                conn.Open();
...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...