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.

Другие вопросы по тегам