Каков хороший способ избавиться от зависимости от StreamReader / FileStream для модульных тестов? - PullRequest
11 голосов
/ 12 февраля 2011

Вот сценарий:

У меня есть метод, который читает файл через FileStream и StreamReader в .NET.Я хотел бы протестировать этот метод и каким-то образом удалить зависимость от объекта StreamReader.

В идеале я хотел бы иметь возможность предоставить собственную строку тестовых данных вместо использования реального файла.Прямо сейчас метод использует метод StreamReader.ReadLine повсюду.Каков подход к изменению дизайна, который у меня есть сейчас, чтобы сделать этот тест возможным?

Ответы [ 4 ]

11 голосов
/ 12 февраля 2011

Зависит от Stream и TextReader.Тогда ваши юнит-тесты могут использовать MemoryStream и StringReader.(Или загрузите ресурсы из вашей тестовой сборки, если необходимо.)

Обратите внимание, как ReadLine изначально объявлено TextReader, , а не StreamReader.

3 голосов
/ 12 февраля 2011

Самое простое решение состоит в том, чтобы метод принимал Stream в качестве параметра вместо открытия своего собственного FileStream. Фактический код может передать FileStream как обычно, в то время как ваш метод тестирования может использовать другой FileStream для тестовых данных или MemoryStream, заполненный тем, что вы хотели протестировать (для этого не требуется файл).

2 голосов
/ 12 февраля 2011

Вдобавок ко всему, я бы сказал, что это прекрасная возможность исследовать достоинства Dependency Injection .

Возможно, вы захотите пересмотреть метод, чтобы он принял делегата, который возвращает содержимое файла.Один делегат (рабочий) может использовать классы в System.IO, а второй (для модульного тестирования) возвращает содержимое непосредственно в виде строки.

0 голосов
/ 14 августа 2014

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

public class FileParser
{
    private readonly TextReader _textReader;

    public FileParser(TextReader reader)
    {
        _textReader = reader;
    }

    public List<TradeInfo> ProcessFile()
    {
        var rows = _textReader.ReadLine().Split(new[] { ',' }).Take(4);
        return FeedMapper(rows.ToList());
    }

    private List<TradeInfo> FeedMapper(List<String> rows)
    {
        var row = rows.Take(4).ToList();
        var trades = new List<TradeInfo>();
        trades.Add(new TradeInfo { TradeId = row[0], FutureValue = Convert.ToInt32(row[1]), NotionalValue = Convert.ToInt32(row[3]), PresentValue = Convert.ToInt32(row[2]) });
        return trades;
    } 
}

, а затем Mock с помощью Rhino Mock

public class UnitTest1
{
    [Test]
    public void Test_Extract_First_Row_Mocked()
    {            
        //Arrange
        List<TradeInfo> listExpected = new List<TradeInfo>();
        var tradeInfo = new TradeInfo() { TradeId = "0453", FutureValue = 2000000, PresentValue = 3000000, NotionalValue = 400000 };
        listExpected.Add(tradeInfo);
        var textReader = MockRepository.GenerateMock<TextReader>();
        textReader.Expect(tr => tr.ReadLine()).Return("0453, 2000000, 3000000, 400000");
        var fileParser = new FileParser(textReader);
        var list = fileParser.ProcessFile();           
        listExpected.ShouldAllBeEquivalentTo(list);         

    }
}

НО вопрос заключается в том,Хорошей практикой является передача такого объекта из клиентского кода, но я чувствую, что с ним нужно обращаться с помощью класса, ответственного за обработку.Я согласен с идеей использования sep-делегата для реального кода и одного для модульного тестирования, но опять же, это немного лишнего кода в производстве.Я могу быть немного потерян с идеей внедрения зависимостей и насмешек над даже открытием / чтением файлового ввода-вывода, что на самом деле не является кандидатом для модульного тестирования, но логика обработки файла - это то, что можно проверить, просто передав строковое содержимое файла (AAA23 ^ YKL890 ^ 300000 ^ TTRFGYUBARC).

Любые идеи, пожалуйста!Спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...