2015-08-16 1 views
2

Я использую Test.Hspec.Wai.JSON для проверки возвращаемого значения моих конечных точек api. Я заметил, что всякий раз, когда я создаю json со значением 0.0, когда тест запускается, он преобразует его в 0 (Int), и если api возвращает 0.0, тест терпит неудачу.Проблема с Aeson или Wai.JSON QuasiQuoter - конвертирует от 0.0 до 0

let j = [json|{"test":0.0}|] 
request "GET" "some_url" [("Content-Type", "application/json")] "" 
     `shouldRespondWith` j {matchStatus = 200} 

    body mismatch: 
    expected: {"test":0} ---> this is the issue (0.0 has become 0) 
    but got: {"test":0.0} 

Я не настолько продвинутый в Haskell, чтобы выяснить, где в библиотечном коде это происходит. Я посмотрел исходный код для Test.Hspec.Wai.JSON и, похоже, полагался на Aeson.QQ, поэтому не совсем уверен в источнике проблемы. Это Test.Hspec.Wai.JSON source и это Aeson.QQ Source

В связи с этим, моей работой вокруг была написать FromJSON экземпляр для разбора всего ответа и проверить против заполненной записи. Это немного утомительно.

Любые предложения относительно того, что в коде библиотеки вызывает это? И как это исправить?

Спасибо,

ответ

3

Подозреваемый, как представляется, эта линия Data.Aeson.QQ:

toExp (JsonNumber n) = [|Number (fromRational $(return $ LitE $ RationalL (toRational n)))|] 

Он преобразует число в Rational, преобразует его в выражение Haskell, а затем полученное выражение затем включите он возвращается в Number. Это в конечном итоге отбрасывает тот факт, что это был 0.0, а не 0.

Это обычно не проблема, поскольку Aeson правильно определяет ==, чтобы сделать Number с равными значениями равными. Это становится актуальной проблемой с Test.Hspec.Wai.JSON; способ, которым он работает, состоит в том, что он кодирует объект обратно в ByteString и ожидает, что он точно соответствует ему.

Хотя Data.Aeson.QQ является основной причиной вашей проблемы, я бы не стал ее обвинять. Вместо этого Test.Hspec.Wai.JSON не должен сериализовать объекты JSON и ожидать, что их представления будут эквивалентными. Скорее, это должно быть десериализация фактического ответа и сравнение декодированных объектов для равенства. (В конце концов, число с плавающей запятой/integer не является единственной возможной проблемой, а также не сможет обрабатывать переопределенные ключи объектов.) Я не знаком с Hspec, поэтому я не уверен, как вы сделайте это.

+0

спасибо. В этом есть смысл. Наверное, сейчас я просто буду разбирать всю запись. Кстати, по какой-либо причине 'json', похоже, работает независимо от порядка ключей, пока это плоский объект, а не массив. – Ecognium

+0

@Ecognium: порядок ключей в вашем случае не имеет значения, потому что вы используете Aeson как в своих тестах, так и в реализации веб-сервиса, а Aeson будет нормализовать порядок ключей во время сериализации. Однако, если вы использовали что-то иное, чем Aeson в своем веб-сервисе, которое не соглашалось с Aeson в том, как должны выполняться ключевые заказы, ваш тест будет говорить, что ответы отличаются, когда они семантически эквивалентны. – icktoofay

Смежные вопросы