Существует ли сопоставление RSpec2 для сопоставления хэшей?
Примечание для будущих читателей: думаете, что RSpec не считает ваши хэши равными? Возможно, это OrderedHash, но из регулярного вывода RSpec вы не можете сказать. Это была проблема, вызвавшая этот пост.
Оригинальный вопрос:
Предположим, что у меня есть спецификация, где я хочу проверить, что метод генерирует соответствующий хэш.
it 'should generate the Hash correctly' do
expected = {:foo => 1, 'baz' => 2}
subject.some_method_that_should_generate_the_hash.should == expected
end
Это часто терпит неудачу, потому что разные хэши с одинаковыми парами ключ-значение могут возвращать свои пары в другом упорядоченном порядке. Результаты выглядят так:
Failure/Error: subject.some_method_that_should_generate_the_hash.should == expected
expected: {:foo => 1, 'baz' => 2},
got: {'baz' => 2, :foo => 1}
Для массивов это решается с помощью оператора = ~. Однако это не работает для хэшей. На данный момент я прибегал к
it 'should generate the Hash correctly' do
expected = {:foo => 1, 'baz' => 2}
subject.some_method_that_should_generate_the_hash.each {|k,v|
v.should == expected[k]
}
end
но это выглядит излишне подробным. Я ожидаю, что для этого будет очевидным решением. Могу ли я что-то забыть в документах или не имеет у RSpec надлежащего совпадения для беззаботного равенства Хэша?
Ответы
Ответ 1
describe 'Hash' do
let(:x) { { :a => 1, :b => 2 } }
let(:y) { { :b => 2, :a => 1 } }
it "should be equal with ==" do
x.should == y
end
end
Пропуска. Я не уверен, что происходит в вашем конкретном случае. У вас есть некоторые неудачные примеры, которыми вы можете поделиться?
Программирование Ruby имеет это, чтобы сказать:
Равенство - два хэша равны, если они имеют одинаковое значение по умолчанию, они содержат одинаковое количество ключей и значение, соответствующее каждому ключу в первый хэш равен (используя ==), чтобы значение для того же ключа в второй.
Ответ 2
С 8 месяцев драгоценный камень rspec-matchers
поддерживает хэши соответствия:
expected.should be_hash_matching(subhash_or_equal)
см. здесь для более подробной информации: https://github.com/rspec/rspec-expectations/pull/79
Ответ 3
Я считаю, что eql? метод проверяет только то, что два хэша имеют один и тот же контент
Так что IIRC в Rspec2 вы можете сделать:
expected = {:foo => 1, 'baz' => 2}
expected.should be_eql({'baz' => 2, :foo => 1})
И тест должен пройти