DbConnection без Db с использованием DataSet в памяти (или аналогичного) в качестве источника

Я пытаюсь провести модульное тестирование нескольких классов .NET, которые (по веским причинам дизайна) требуют, чтобы DbConnections выполняла свою работу. Для этих тестов у меня есть определенные данные в памяти, которые можно использовать в качестве входных данных для этих классов.

Эти данные в памяти можно легко выразить как DataTable (или DataSet, содержащий этот DataTable), но если бы другой класс был более подходящим, я мог бы его использовать.

Если бы я каким-то волшебным образом смог получить DbConnection, представляющий соединение с данными в памяти, то я мог бы построить свои объекты, заставить их выполнять свои запросы к данным в памяти и гарантировать, что их вывод соответствует ожиданиям. Есть ли способ получить соединение DbConnection с данными в памяти? У меня нет свободы устанавливать дополнительное стороннее программное обеспечение, чтобы это произошло, и в идеале я не хочу прикасайтесь к диску во время тестов.


person Jerry Federspiel    schedule 25.03.2009    source источник


Ответы (3)


Можете ли вы использовать IDbConnection и имитировать его вместо того, чтобы использовать DbConnection? Мы делаем что-то подобное, передаем макет DataSet. DataSet.CreateDataReader возвращает DataTableReader, который наследуется от DbDataReader.

Мы обернули DbConnection в наш собственный интерфейс, подобный IDbConnection, к которому мы добавили метод ExecuteReader (), который возвращает класс, реализующий те же интерфейсы, что и DbDataReader. В нашем макете ExecuteReader просто возвращает то, что обслуживает DataSet.CreateDataReader.

Звучит окольным путём, но очень удобно создать DataSet, возможно, с множеством наборов результатов. Мы называем DataTables в честь сохраненных процессов, результаты которых они представляют, и наш макет IDbConnection захватывает правильный Datatable в зависимости от процесса, который вызывает клиент. DataTable также реализует CreateDataReader, так что все готово.

person n8wrl    schedule 26.03.2009

Подход, который я использовал, - это создание базы данных Sqlite в памяти. Это можно сделать, просто вставив пакет NuGet System.Data.SQLite.Core в свой проект модульного тестирования, вам не нужно устанавливать какое-либо программное обеспечение где-либо еще.

Хотя это звучит как действительно очевидная идея, только когда я взглянул на модульные тесты Dapper, я решил использовать эту технику сам! См. Метод GetSqliteConnection в

https://github.com/StackExchange/dapper-dot-net/blob/bffb0972a076734145d92959dabbe48422d12922/Dapper.Tests/Tests.cs

Следует помнить, что если вы создаете базу данных sqlite в памяти и создаете и заполняете таблицы, вам нужно быть осторожным, чтобы не закрыть соединение перед выполнением ваших тестовых запросов, потому что открытие нового соединения в памяти даст вам подключение к новой базе данных в памяти, не к базе данных, которую вы только что тщательно подготовили для своих тестов! Для некоторых из моих тестов я использую специальную реализацию IDbConnection, которая поддерживает соединение открытым, чтобы избежать этой ловушки - например.

https://github.com/ProductiveRage/SqlProxyAndReplay/blob/master/Tests/StaysOpenSqliteConnection.cs

person Dan Roberts    schedule 28.07.2016

TypeMock? (Однако вам нужно будет «установить» его).

Будьте осторожны, предполагая, что Data * может дать вам подходящие ловушки для тестирования - в целом это худший случай. Но вы говорите «Причины хорошего дизайна», так что я уверен, что это все покрыто: D

person Ruben Bartelink    schedule 26.03.2009