Фиктивные подключения к базе данных в haskell

#haskell #hunit

Вопрос:

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

Ответ №1:

Передайте функцию, которая выполняет запрос базы данных, в свой код в качестве параметра, вместо того, чтобы она была «запрограммирована». Во время тестов передайте коду функцию макета. В рабочей среде передайте функцию, которая действительно выполняет запрос к базе данных.

Этот новый параметр функции должен находиться на правильном уровне абстракции. Например, что-то вроде

 queryDbForClient :: Connection -> SQLString -> ClientId -> IO (Maybe RowData)
 

возможно, это плохая идея, потому что это по-прежнему заставляет тестируемый код осознавать, что существуют такие вещи, как Connection строки s и SQL. Что-то вроде этого

 findClientById :: ClientId -> IO (Maybe Client) 
 

вероятно, было бы лучше, потому что тогда вы можете свободно передавать функции, которые вообще не используют Connection типы, специфичные для БД. Они могут, например, быть подкреплены ссылкой в памяти.

Обратите внимание, что вы можете построить findClientById из queryDbForClient частичного приложения и немного отобразить результат. Но это должно быть задачей некоторого кода настройки, а не основного кода, который вы хотите протестировать.


Как только вы начнете передавать функции таким образом для удобства тестирования и настройки, начнут появляться некоторые распространенные проблемы. Например, что делать, если у меня несколько зависимостей? Передача их всех в качестве позиционных параметров-это тяжелая работа. Это может привести к передаче их вместе в записи функций, возможно, с использованием Has подобных типов, чтобы не привязывать ваш основной код к какой-либо конкретной записи.