RSpec + Rubocop - почему receive_message_chain является запахом кода? - PullRequest
0 голосов
/ 06 декабря 2018

Я собираюсь написать спецификации для моего пользовательского валидатора, который использует эту цепочку, чтобы проверить, является ли файл, прикрепленный с ActiveStorage, txt:

return if blob.filename.extension.match?('txt')

Обычно я был быв состоянии заглушить это с помощью этого вызова:

allow(attached_file).to receive_message_chain(:blob, :byte_size) { file_size }

Рубокоп говорит, что это преступление и указывает мне на документы: https://www.rubydoc.info/gems/rubocop-rspec/1.7.0/RuboCop/Cop/RSpec/MessageChain

Я должен объявить двойнойдля blob и byte_size и заглушки их в отдельные строки, заканчивающиеся 5 строками кода вместо 1. Я что-то здесь упускаю?

1 Ответ

0 голосов
/ 27 декабря 2018

Почему я должен избегать создания цепочек сообщений?

Мне нужно было бы объявить double для blob и byte_size и заглушки их в отдельных строках, заканчивающихся 5 строками кодавместо 1.

Это, собственно, и есть точка.Наличие этих 5 строк, вероятно, заставит вас чувствовать себя немного неловко.Это можно рассматривать как положительное расчетное давление .Сложность вашей тестовой установки говорит вам о необходимости взглянуть на реализацию.Использование #receive_message_chains позволяет нам чувствовать себя хорошо с проектами, которые заранее раскрывают сложные взаимодействия.

Один из авторов RSpec объясняет это в выпуске GitHub .

* 1017.* Что я могу сделать вместо этого?

Один из вариантов - прикрепить файл записи к записи на этапе настройки вашего теста:

before do
  file_path = Rails.root.join("spec", "fixtures", "files", "text.txt")

  record.attribute.attach(io: File.open(file_path), filename: "text.txt")
end

.сквозной валидатор, без какой-либо заглушки.


Другой вариант - извлечь именованный метод, а затем заглушить его.

В вашем валидаторе:

def allowed_file_extension?
  blob.filename.extension.match?("txt")
end

В вашем тесте:

before do
  allow(validator).to receive(:allowed_file_extension?).and_return(true)
end

Это дает дополнительное преимущество, заключающееся в том, чтобы сделать код немного понятнее, назвав концепцию.(Ничто не мешает вам добавить этот метод, даже если вы используете тестовое устройство.)

...