2015-05-27 1 views
0

Я немного не понимаю, как написать спецификацию RSpec 3.2.x, которая проверяет, содержит ли список, содержащий хотя бы один элемент, который удовлетворяет условию.RSpec matcher, который проверяет коллекцию, чтобы включить элемент, который удовлетворяет лямбда

Вот пример:

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 неудача не даст мне никакого значимого вывода, так я думал, что там должен быть встроенный способ соответствовать этому.

Любые другие предложения о том, как структурировать тест, также приветствуются.

Edit: Чтобы было ясно - эти изменения список ChangeObject, поэтому мне нужно, чтобы получить доступ к их .key и .value методу

ответ

2

В RSpec 3 matchers are fully composable, что означает, что вы можете передайте любой объект, который реализует протокол Ruby's === (включая совпадение!) до 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') 
+0

Отлично. Я не знал о 'an_object_having_attributes'. Спасибо! – Tigraine

+1

Это псевдоним 'has_attributes', нового совпадения, введенного в RSpec 3.1: http://rspec.info/blog/2014/09/rspec-3-1-has-been-released/#expectations-new-haveattributes- согласовани –

1

Попробуйте

expect(changes).to be_any{ |x| //logic to match } 
+0

К сожалению, это не работает, так как это нет хеша, кроме объекта. Я уточню вопрос – Tigraine

+0

Я также не могу проверить равенство соответствующего объекта, так как объект построен внутри класса, и я не хочу нарушать правила видимости. – Tigraine

+0

В этом случае «ожидать (изменения) .to be_include {| x | x.key == 'name' && value == 'test'}" выполнит задание – Kamesh

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