#ruby #rspec #rspec-mocks
#ruby #rspec #rspec-издевается
Вопрос:
Я пишу ожидание, которое проверяет, вызывался ли метод два раза с разными аргументами и возвращает ли он разные значения. На данный момент я просто записываю ожидание дважды:
expect(ctx[:helpers]).to receive(:sanitize_strip).with(
%{Stringn<a href="http://localhost:3000/">description</a> <br/>and newlinen<br>},
length: nil
).and_return('String description and newline')
expect(ctx[:helpers]).to receive(:sanitize_strip).with(
%{Stringn<a href="http://localhost:3000/">description</a> <br/>and newlinen<br>},
length: 15
).and_return('String descr...')
Интересно, могу ли я использовать receive ... exactly ... with ... and_return ...
вместо этого; что-то вроде:
expect(ctx[:helpers]).to receive(:sanitize_strip).exactly(2).times.with(
%{Stringn<a href="http://localhost:3000/">description</a> <br/>and newlinen<br>},
length: nil
).with(
%{Stringn<a href="http://localhost:3000/">description</a> <br/>and newlinen<br>},
length: 15
).and_return('String descr...', 'String description and newline')
Приведенный выше код не работает, он выдает следующую ошибку:
1) Types::Collection fields succeeds
Failure/Error: context[:helpers].sanitize_strip(text, length: truncate_at)
#<Double :helpers> received :sanitize_strip with unexpected arguments
expected: ("Stringn<a href="http://localhost:3000/">description</a> <br/>and newlinen<br>", {:length=>15})
got: ("Stringn<a href="http://localhost:3000/">description</a> <br/>and newlinen<br>", {:length=>nil})
Diff:
@@ -1,3 1,3 @@
["Stringn<a href="http://localhost:3000/">description</a> <br/>and newlinen<br>",
- {:length=>15}]
{:length=>nil}]
Есть ли способ использовать receive ... exactly ... with ... and_return ...
с разными with
аргументами?
Комментарии:
1. Может быть,
hash_including({})
вместоlength: nil
? relishapp.com/rspec/rspec-mocks/docs/setting-constraints /…
Ответ №1:
Есть rspec-any_of
драгоценный камень, который допускает следующий синтаксис путем добавления all_of
средства сопоставления аргументов:
expect(ctx[:helpers]).to receive(:sanitize_strip).with(
%{Stringn<a href="http://localhost:3000/">description</a> <br/>and newlinen<br>}
all_of({length: 15}, {length: nil})
)
.and_return('String descr...', 'String description and newline')
.twice
Комментарии:
1. Потрясающе! И спасибо вам и вашим коллегам за драгоценный камень!
Ответ №2:
Не используя дополнительный gem, вы могли бы вызвать обычные переменные expect ... to receive ... with ... and_return ...
with из each
блока:
describe '#sanitize_strip' do
let(:html) do
%{Stringn<a href="http://localhost:3000/">description</a> <br/>and newlinen<br>}
end
let(:test_data) do
[
[[html, length: nil], 'String description and newline'],
[[html, length: 15], 'String descr...']
]
end
it 'returns sanitized strings stripped to the number of characters provided' do
test_data.each do |args, result|
expect(ctx[:helpers]).to receive(:sanitize_strip).with(*args).and_return(result)
end
# Trigger the calls to sanitize_strip
end
end