Существует ли сопоставление 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})

И тест должен пройти