TL; DR самый прямой способ проверить это, чтобы сортировать массивы перед проверкой их равенства.
json.map{|d| d["id"]}.sort.must_equal Database.all.pluck(:id).sort
Еще здесь? Хорошо. Давайте поговорим о сравнении элементов в массиве.
Как бы то ни было, карта {} уже не имеет никакого отношения к тесту и добавляет беспорядок, я бы предпочел не добавлять еще больше.
Ну, это часть проблемы. Ваш JSON содержит массив объектов JSON, а при вызове Database.pluck
будет возвращено что-то еще, предположительно целые. Вам нужно преобразовать объекты JSON и ваш запрос в один и тот же тип данных. Поэтому неточно сказать, что .map{}
не имеет значения, и если это похоже на беспорядок, это потому, что вы делаете так много всего в своем утверждении. Попробуйте разделив эту строку кода на части и используя о намерениях разоблачающие имена:
sorted_json_ids = json.map{|d| d["id"]}.sort
sorted_db_ids = Database.order(:id).pluck(:id)
sorted_json_ids.must_equal sorted_db_ids
Это несколько строк кода в тесте, но лучше передает намерение. И все же я слышу ваши слова «нерелевантные» и «беспорядок», повторяющиеся в моем сознании. Держу пари, вам не нравится это решение. «Слишком много работы!» И «Почему I несут ответственность за это?» Ладно ладно. У нас больше возможностей. Как насчет более умного утверждения?
У RSpec есть приятный маленький помощник по имени match_array
, который делает в значительной степени то, что вы ищете. Он sorts and compares arrays и печатает хорошее сообщение, если они не совпадают. Мы могли бы сделать что-то подобное.
def assert_matched_arrays expected, actual
assert_equal expected.to_ary.sort, actual.to_ary.sort
end
it "fetches a list of all databases" do
get "/v1/databases"
json = JSON.parse(response.body)
assert_matched_arrays Database.pluck(:id), json.map{|d| d["id"]}
end
«Но это утверждение, а не ожидание!» Да, знаю. Расслабьтесь.Вы можете включить утверждение в ожидании, вызвав infect_an_assertion
. Но для этого вы, вероятно, захотите добавить метод assertion, чтобы он мог использоваться в каждом тесте Minitest. Так что в моем test_helper.rb
файле я хотел бы добавить следующее:
module MiniTest::Assertions
##
# Fails unless <tt>exp</tt> and <tt>act</tt> are both arrays and
# contain the same elements.
#
# assert_matched_arrays [3,2,1], [1,2,3]
def assert_matched_arrays exp, act
exp_ary = exp.to_ary
assert_kind_of Array, exp_ary
act_ary = act.to_ary
assert_kind_of Array, act_ary
assert_equal exp_ary.sort, act_ary.sort
end
end
module MiniTest::Expectations
##
# See MiniTest::Assertions#assert_matched_arrays
#
# [1,2,3].must_match_array [3,2,1]
#
# :method: must_match_array
infect_an_assertion :assert_matched_arrays, :must_match_array
end
Теперь ваше утверждение может быть использован в любом испытании, и ваши ожидания будут доступны на каждом объекте.
it "fetches a list of all databases" do
get "/v1/databases"
json = JSON.parse(response.body)
json.map{|d| d["id"]}.must_match_array Database.pluck(:id)
end
ВНИМАНИЕ: Вы должны использовать дополнительные драгоценные камни для этой работы, то есть: Shoulda –