Как мне протестировать метод, заполняющий список из DataReader?
-
09-06-2019 - |
Вопрос
Итак, я работаю над устаревшим кодом, который требует больших ручных операций с базой данных.Я пытаюсь сохранить некое подобие качества, поэтому максимально использую TDD.
Код, над которым я работаю, необходимо заполнить, скажем, List<Foo>
из DataReader, который возвращает все поля, необходимые для функционирования Foo.Однако, если я хочу убедиться, что код действительно возвращает один элемент списка на одну строку базы данных, я пишу тестовый код, который выглядит примерно так:
Expect.Call(reader.Read()).Return(true);
Expect.Call(reader["foo_id"]).Return((long) 1);
// ....
Expect.Call(reader.Read()).Return(true);
Expect.Call(reader["foo_id"]).Return((long) 2);
// ....
Expect.Call(reader.Read()).Return(false);
Это довольно утомительно и к тому же довольно легко сломается.
Как мне следует подойти к этой проблеме, чтобы результатом не стала огромная путаница хрупких тестов?
Кстати, сейчас я использую для этого Rhino.Mocks, но могу изменить его, если результат будет достаточно убедительным.При условии, что альтернативой не является TypeMock, потому что их лицензионное соглашение было слишком пугающим, на мой вкус, в последний раз, когда я проверял.
Редактировать:В настоящее время я также ограничен C # 2.
Решение
Чтобы сделать это менее утомительным, вам нужно будет инкапсулировать/реорганизовать сопоставление между DataReader и объектом, который вы держите в списке.Чтобы инкапсулировать эту логику, нужно выполнить несколько шагов.Если вы хотите пойти по этому пути, я могу опубликовать для вас код.Я просто не уверен, насколько практично было бы опубликовать код здесь, на StackOverflow, но я могу попытаться сделать его кратким и по существу.В противном случае вам придется выполнять утомительную задачу повторения каждого ожидания метода доступа к индексу для читателя.Процесс инкапсуляции также избавит вас от строк и сделает их более пригодными для повторного использования в ваших тестах.
Кроме того, на данный момент я не уверен, насколько вы хотите сделать существующий код более тестируемым.Поскольку это устаревший код, который не был создан с учетом тестирования.
Другие советы
Я подумал о том, чтобы опубликовать немного кода, но потом вспомнил о курсе JP Boodhoo Nothin But .NET.У него есть пример проекта которым он делится, созданным во время одного из его занятий.Проект размещен на Google-код и это хороший ресурс.Я уверен, что здесь есть несколько полезных советов, которые вы сможете использовать, а также идеи по рефакторингу сопоставления.Весь проект был построен с использованием TDD.
Вы можете поместить экземпляры Foo в список и сравнить объекты с тем, что вы читаете:
var arrFoos = new Foos[]{...}; // what you expect
var expectedFoos = new List<Foo>(arrFoos); // make a list from the hardcoded array of expected Foos
var readerResult = ReadEntireList(reader); // read everything from reader and put in List<Foo>
Expect.ContainSameFoos(expectedFoos, readerResult); // compare the two lists
Кокос,
Там пара вещей не так.Во-первых, такой подход означает, что мне нужно сначала создать Foos, а затем передать их значения программе чтения макетов, которая ничего не делает для уменьшать количество кода, который я пишу.Во-вторых, если значения проходят через считыватель, Foos не будет такой же Foos (ссылочное равенство).Они могут быть равный, но даже это предполагает слишком большую часть класса Foo, которую я не смею трогать на данный момент.
Просто чтобы уточнить: вы хотите иметь возможность проверить, что ваш вызов SQL Server вернул некоторые данные, или что, если у вас есть какие-то данные, вы можете отобразить их обратно в модель?
Если вы хотите проверить свой вызов в SQL, он вернул некоторые данные, мой ответ нашел здесь
@Торан:Я тестирую программное сопоставление данных, возвращаемых из базы данных, с моделью домена в кавычках.Поэтому я хочу издеваться над соединением с базой данных.Что касается другого типа тестов, я бы выбрал комплексное интеграционное тестирование.
@Дол:Полагаю, вы неплохо с этим справились, и я боялся, что это может быть так.Если у вас есть ссылки на какие-либо статьи или тому подобное, где кто-то проделал грязную работу и разложил ее на более легко усваиваемые шаги, я был бы признателен.Примеры кода тоже не помешали бы.У меня есть представление о том, как подойти к этой проблеме, но прежде чем я действительно осмелюсь это сделать, мне нужно будет сделать другие вещи, и если тестирование потребует утомительных издевательств, то я так и сделаю.