Как unit-test класс, который должен иметь конкретный файл

В настоящее время я пытаюсь изучить правильный unit тест. Итак, теперь я пытаюсь написать unit-тесты для класса, который должен отображать данные из XML файла в соответствующие объекты. Конечно, вся функциональность класса зависит от существования соответствующего XML файла. XML файл загружается в конструктор класса.

Я использую С# с NUnit. Пока у меня два теста:

[Test]
public void ShouldAllowInstanceToBeCreatedWhenXMLFileIsPresent()
{
    if (File.Exists(SettingsReader.XML_SETTINGS_PATH))
    {
        SettingsReader settingsReader = new SettingsReader();
        Assert.AreNotEqual(null, settingsReader);
    }
}

[Test]
[ExpectedException("Telekanzlei.Clientmanager.XMLDataLayer.XMLFileNotFoundException")]
public void ShouldThrowExceptionWhenXMLFileIsNotPresent()
{
    if (!File.Exists(SettingsReader.XML_SETTINGS_PATH))
    {
        SettingsReader settingsReader = new SettingsReader();
    }
        else
            throw new XMLFileNotFoundException();
    }

Я не уверен, что проверка наличия файла в тесте - это правильный способ, поэтому любые предложения по этим тестам тоже приветствуются. Но мой вопрос в том, как продолжить следующие тесты. Очевидно, что все последующие тесты будут терпеть неудачу, если XML файл отсутствует.

Итак, я предполагаю, что XML файл присутствует, имея в виду, что неудачный тест может означать, что это не так? Это мне не показалось бы.

Существует ли общий шаблон для решения такой проблемы?

спасибо для любой помощи

edit: переписал второй тест, так как он потерпел неудачу, если файл действительно присутствовал...

edit2: Может ли это помочь вам рассказать, что на самом деле делает SettingsReader. Пока это выглядит так:

public class SettingsReader
{
    public static readonly string XML_SETTINGS_PATH = "C:\\Telekanzlei\\Clientmanager_2.0\\Settings.xml";

    public XElement RootXElement { get; private set; }

    public SettingsReader()
    {
        if (!File.Exists(XML_SETTINGS_PATH))
            throw new XMLFileNotFoundException();
        using (var fs = File.OpenRead(XML_SETTINGS_PATH))
        {
            RootXElement = XElement.Load(fs);
        }
    }


}

Я не уверен, но я думаю, что StreamReader не был бы здесь, не так ли?

Ответ 1

Проблема не в ваших модульных тестах, а в дизайне класса. Я бы предложил рефакторинг класса, чтобы он не открывал файл, а вместо этого работал с потоком. Тогда ваши модульные тесты могут просто заменить поток файлов для потока памяти - просто!:)

public class SettingsReader()
{
    public SettingsReader(System.IO.StreamReader reader)
    {
        // read contents of stream...
    }
}

// In production code:
new SettingsReader(new StreamReader(File.Open("settings.xml")));

// In unit test:
new SettingsReader(new StringReader("<settings>dummy settings</settings>"));

Помните, что открытие файлов и данных настроек синтаксиса - это две очень разные проблемы.

Ответ 2

Если вам нужно предложить использовать метод SetUp для копирования или проверки наличия файла. Я предлагаю убедиться, что файл присутствует, добавив его в тестовый проект и пометив его как "копировать всегда", как только вы получите эту работу, нет необходимости перепроверять ее.
Если у вас много тестов, требующих внешних файлов, возможно, вы должны использовать MsTest - у него есть атрибут, называемый DeploymentItem, который гарантирует, что файл будет скопирован в то же место, что и тест.

Ответ 3

Рассмотрим переписывание кода, чтобы зависимости могли быть переданы или каким-то другим образом зачеркнуты для кода, который вы хотите провести с помощью модуля.

т.е. передать что-то вроде экземпляра "IMySettingsFileProvider" в конструктор SettingsReader, где IMySettingsFileProvider.SettingsXml возвращает некоторый установочный поток. Таким образом, вы можете обмануть интерфейс IMySettingsFileProvider для теста, а не требовать, чтобы файл присутствовал на диске.

Ответ 4

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

[SetUp]
public void Setup()
{
    Assume.That(File.Exists(SettingsReader.XML_SETTINGS_PATH));
}