#ruby-on-rails #ruby #ruby-on-rails-4 #rspec #controller
#ruby-on-rails #ruby #ruby-on-rails-4 #rspec #контроллер
Вопрос:
Я нахожусь в процессе рефакторинга некоторых спецификаций для использования let
вместо переменных экземпляра.
Я столкнулся с проблемой со спецификацией контроллера:
describe "#destroy" do
let(:gallery){ create(:gallery) }
context "when not authenticated" do
it {
expect{
delete :destroy, id: gallery
}.to_not change{ Gallery.count }
should redirect_to new_user_session_path
}
end
end
Похоже, что проблема возникает из-за использования ‘let because it lazy-creates gallery the first time it is referenced which in this case is inside the expect block. So the
Gallery.count` на самом деле увеличивается с 0 до 1, что приводит к сбою теста. На данный момент тест завершается неудачно из-за реализации RSpec, а не из-за кода, который он тестирует.
Очевидно, я мог бы вернуться к созданию камбуза в before
блоке и сохранить его в переменной экземпляра, но это кажется немного хакерским. Обходной путь заключается в добавлении блока before, который ссылается на галерею, заставляя его оцениваться перед ожидаемым блоком:
before { gallery }
Каков наилучший способ структурировать эту спецификацию?
Как я должен структурировать этот тест?
Ответ №1:
Не самый элегантный способ, но это работает для меня:
describe "#destroy" do
let(:gallery){ create(:gallery) }
context "when not authenticated" do
it {
gallery
expect{
delete :destroy, id: gallery
}.to_not change{ Gallery.count }
should redirect_to new_user_session_path
}
end
end
Если вы не меняете значение gallery
между тестами в группе, то на самом деле нет необходимости использовать let () в первую очередь, поэтому вы можете просто выполнить блок before, как вы упомянули, и он немного более читабелен:
describe "#destroy" do
context "when not authenticated" do
before { @gallery = create(:gallery) }
it {
expect{
delete :destroy, id: @gallery
}.to_not change{ Gallery.count }
should redirect_to new_user_session_path
}
end
end