RSpec matcher, который проверяет коллекцию, чтобы включить элемент, который удовлетворяет лямбда
Я немного растерялся относительно того, как написать спецификацию RSpec 3.2.x, которая проверяет, содержит ли список хотя бы один элемент, удовлетворяющий условию.
Вот пример:
model = Invoice.new
model.name = 'test'
changes = model.changes
expect(changes).to include { |x| x.key == 'name' && x.value == 'test' }
Будут и другие (автоматические) изменения в списке изменений, поэтому я не хочу проверять, что есть только одно конкретное изменение, и я также не хочу полагаться на порядок expect(changes.first)...
поэтому мне нужен способ указать, что хотя бы одно изменение в списке удовлетворяет условию.
Я мог бы сделать что-то вроде этого:
result = changes.any? { |x| x.key == 'name' .. }
expect(result).to eq(true)
Но тогда сбой rspec не дал бы мне никакого значимого вывода, поэтому я подумал, что должен быть встроенный способ, чтобы соответствовать этому.
Любые другие предложения о том, как структурировать тест, также приветствуются.
Изменить: чтобы быть ясно - изменения являются списком ChangeObject, поэтому мне нужно получить доступ к их .key
а также .value
метод
2 ответа
В RSpec 3 сопоставления полностью компонуются, что означает, что вы можете передать любой объект, который реализует Ruby ===
протокол (включая совпадение!) include
и это будет работать правильно. Лямбды в Ruby 1.9 реализуют ===
протокол, который означает, что вы можете сделать это:
expect(changes).to include(lambda { |x| x.key == 'name' && value == 'test' })
Тем не менее, это не даст вам большого сообщения об ошибке (поскольку у RSpec нет способа генерировать описание лямбды). Я не уверен где value
исходит из вашего примера, но если он предназначен для x.value
Вы могли бы использовать have_attributes
(или же an_object_having_attributes
для лучшей читаемости)
expect(changes).to include an_object_having_attributes(key: 'name', value: 'test')
Попробуй это
expect(changes).to be_any{ |x| //logic to match }