У меня есть такой пример:
it 'does not change payment status, cancellation reason, or output cancellation message' do
expect { job }
.not_to change { payment.reload.payment_status }.from('transferring')
.and change { payment.reload.cancellation_reason }.from(nil)
.and output(/Платёж #{payment.uuid} отменён/).to_stdout
end
Но я получаю ошибку
NotImplementedError:
`expect(...).not_to matcher.and matcher` is not supported, since it creates a bit of an ambiguity. Instead, define negated versions of whatever matchers you wish to negate with `RSpec::Matchers.define_negated_matcher` and use `expect(...).to matcher.and matcher`.
Придумай решение
====================================================
Понятно, проблема в том, что RSpec не поддерживает комбинацию not_to
с and
. Давайте решим это с помощью define_negated_matcher
, как и предлагается в сообщении об ошибке.
Вот решение:
# В начале файла или в spec_helper.rb добавим определения негативных матчеров
RSpec::Matchers.define_negated_matcher :not_change, :change
RSpec::Matchers.define_negated_matcher :not_output, :output
# Теперь тест можно переписать так
it 'does not change payment status, cancellation reason, or output cancellation message' do
expect { job }
.to not_change { payment.reload.payment_status }.from('transferring')
.and not_change { payment.reload.cancellation_reason }.from(nil)
.and not_output(/Платёж #{payment.uuid} отменён/).to_stdout
end
Что я сделал:
- Создал негативный матчер
not_change
который является противоположностьюchange
- Создал негативный матчер
not_output
который является противоположностьюoutput
- Заменил конструкцию
expect().not_to change
наexpect().to not_change
Теперь тест должен работать корректно. Такой подход делает тест более читаемым и избегает проблемы с not_to
и and
.
Эти определения матчеров (define_negated_matcher
) лучше вынести в общий файл конфигурации тестов (например, spec_helper.rb или rails_helper.rb), чтобы они были доступны во всех тестах.