Haskell: Как протестировать приложение Spock, которое использует wreq?
Я написал очень простое приложение на Haskell, используя Spock и wreq. Я хочу написать несколько тестов, но я не уверен, как это сделать.
Все, что делает приложение, - это отправляет HTTP-запрос на другой сервер и переводит ответ JSON в удобное для человека сообщение. Вот код, если это помогает. Я хочу написать тест, который утверждает, что понятное для человека сообщение является правильным с учетом определенного ответа JSON.
В Ruby я бы издевался над HTTP-клиентом, в данном случае wreq
, чтобы контролировать ответ JSON, который я получаю, но я не уверен, как, или даже если, чтобы сделать это в Haskell.
Из того, что я собрал из своего исследования, кажется, что переменные типа с ограничением на классы типов - это путь, который для меня выглядит как внедрение зависимостей, но я не уверен, как это сделать в контексте Спока и wreq.
Учебное пособие по тестированию Спока описывает, как тестировать Спока в IO Application
уровень, который звучит великолепно. Часть, в которой я не уверен, заключается в том, как "внедрить" фиктивный HTTP-клиент для управления ответом JSON.
Любая помощь приветствуется!
1 ответ
Если мы хотим поддерживать разные методы составления запроса, мы должны абстрагироваться от них. Вы можете заставить свои обработчики принимать в качестве аргумента функцию, которая выполняет HTTP-запросы, а затем передавать различные функции для тестирования и производства. Если у вас есть более одной связанной функции, поместите их в запись ( шаблон дескриптора).
Если мы используем cabal-install > 2.0 (с командами new-*), другой возможный вариант - использовать сигнатуру модуля для переключения реализаций между набором тестов и конечным исполняемым приложением. Это решение также активно использует функцию внутренних удобных библиотек Cabal.
Основная идея заключается в следующем: мы помещаем наше приложение Spock в его собственную библиотеку, но не делаем его зависимым от wreq напрямую. Вместо этого мы объявляем в той же библиотеке подпись Requests.hsig
как это:
signature SomeSpockApp.Requests where
import Data.Aeson (FromJSON)
data Token
doGET :: FromJSON a => String -> Token -> IO a
Он определяет высокоуровневый интерфейс для выполнения HTTP-запросов. Код в библиотеке импортирует эту подпись. Для остальной части кода в библиотеке, SomeSpockApp.Requests
это просто еще один модуль.
Далее мы определяем вспомогательную библиотеку, которая будет предоставлять фактический модуль SomeSpockApp.Requests
(то же имя, что и подпись, за исключением того, что теперь это hs
файл). Он будет содержать "ложный" код. Конечно определение doGET
должен быть совместим с подписью.
Мы также определяем другую вспомогательную библиотеку с другим SomeSpockApp.Requests
модуль. Это должно зависеть от wreq и выполнять методы нашей подписи, используя функции wreq.
В тестовом наборе мы должны зависеть как от библиотеки приложений Spock, так и от библиотеки mock. Имена сигнатуры и макета модуля реализации выстраиваются идеально, поэтому больше ничего не нужно делать. (Если имена не совпадают, мы можем использовать раздел mixins в файле cabal для переименования модуля).
В исполняемом файле приложения мы должны зависеть как от нашей библиотеки приложений Spock, так и от библиотеки, использующей wreq.