DbConnection без Db, использующего набор данных в памяти (или аналогичный) в качестве источника
-
22-08-2019 - |
Вопрос
Я пытаюсь провести модульное тестирование нескольких .СЕТЕВЫЕ классы, которым (по веским причинам проектирования) требуются DbConnections для выполнения своей работы.Для этих тестов у меня есть определенные данные в памяти, которые я могу предоставить в качестве входных данных этим классам.
Эти данные в памяти можно было бы легко выразить в виде DataTable (или набора данных, который содержит этот DataTable), но если бы другой класс был более подходящим, я мог бы использовать его.
Если бы я каким-то волшебным образом смог получить DbConnection, который представлял бы соединение с данными в памяти, тогда я мог бы создавать свои объекты, заставлять их выполнять свои запросы к данным в памяти и гарантировать, что их выходные данные соответствуют ожиданиям. Есть ли какой-нибудь способ получить DbConnection к данным в памяти? У меня нет возможности устанавливать какое-либо дополнительное стороннее программное обеспечение, чтобы это произошло, и в идеале я не хочу прикасаться к диску во время тестов.
Решение
Вместо того, чтобы использовать DbConnection, можете ли вы использовать IDbConnection и издеваться над ним?Мы делаем что-то подобное, передаем макет набора данных.DataSet.CreateDataReader возвращает DataTableReader, который наследуется от DbDataReader.
Мы внедрили DbConnection в наш собственный интерфейс, подобный IDbConnection, к которому мы добавили метод ExecuteReader(), который возвращает класс, реализующий те же интерфейсы, что и DbDataReader.В нашем макете ExecuteReader просто возвращает, какой DataSet.CreateDataReader обслуживает.
Звучит несколько окольно, но очень удобно создавать набор данных с возможно большим количеством результирующих наборов.Мы называем таблицы данных в честь сохраненных процедур, результаты которых они представляют, и наш макет IDbConnection извлекает правильную таблицу данных на основе процедуры, вызываемой клиентом.DataTable также реализует CreateDataReader, так что все готово.
Другие советы
Подход, который я использовал, заключается в создании базы данных Sqlite в памяти.Это можно сделать, просто подключив System.Data.SQLite.Основной пакет NuGet к вашему проекту модульного тестирования, вам не нужно устанавливать какое-либо программное обеспечение где-либо еще.
Хотя это звучит как действительно очевидная идея, только когда я посмотрел на модульные тесты Dapper, мне пришло в голову самому использовать эту технику!Смотрите метод "GetSqliteConnection" в
Следует помнить одну вещь: если вы создаете базу данных sqlite в памяти, а также создаете и заполняете таблицы, вам нужно быть осторожным и не закрывать соединение перед выполнением тестовых запросов, потому что открытие нового соединения в памяти приведет к подключению к новое база данных в памяти, не база данных, которую вы только что тщательно подготовили для своих тестов!Для некоторых моих тестов я использую пользовательскую реализацию IDbConnection, которая поддерживает соединение открытым, чтобы избежать этой ошибки - например.
https://github.com/ProductiveRage/SqlProxyAndReplay/blob/master/Tests/StaysOpenSqliteConnection.cs
TypeMock?(Однако вам нужно было бы его "установить").
Будьте осторожны, предполагая, что Data * может дать вам надлежащие хукеры для тестирования - в целом это довольно наихудший случай.Но вы говорите о веских дизайнерских соображениях, так что я уверен, что все это учтено: D