#haskell #hunit
Вопрос:
Я пытаюсь написать какой-нибудь простой код в haskell, где есть функция, выполняющая простой запрос к базе данных. Для модульного тестирования я использую HUnit, но не уверен, как я могу имитировать подключение к базе данных и ответ на запрос.
Ответ №1:
Передайте функцию, которая выполняет запрос базы данных, в свой код в качестве параметра, вместо того, чтобы она была «запрограммирована». Во время тестов передайте коду функцию макета. В рабочей среде передайте функцию, которая действительно выполняет запрос к базе данных.
Этот новый параметр функции должен находиться на правильном уровне абстракции. Например, что-то вроде
queryDbForClient :: Connection -> SQLString -> ClientId -> IO (Maybe RowData)
возможно, это плохая идея, потому что это по-прежнему заставляет тестируемый код осознавать, что существуют такие вещи, как Connection
строки s и SQL. Что-то вроде этого
findClientById :: ClientId -> IO (Maybe Client)
вероятно, было бы лучше, потому что тогда вы можете свободно передавать функции, которые вообще не используют Connection
типы, специфичные для БД. Они могут, например, быть подкреплены ссылкой в памяти.
Обратите внимание, что вы можете построить findClientById
из queryDbForClient
частичного приложения и немного отобразить результат. Но это должно быть задачей некоторого кода настройки, а не основного кода, который вы хотите протестировать.
Как только вы начнете передавать функции таким образом для удобства тестирования и настройки, начнут появляться некоторые распространенные проблемы. Например, что делать, если у меня несколько зависимостей? Передача их всех в качестве позиционных параметров-это тяжелая работа. Это может привести к передаче их вместе в записи функций, возможно, с использованием Has
подобных типов, чтобы не привязывать ваш основной код к какой-либо конкретной записи.