Тестирование изоляции контроллера от моделей
Возможно ли (и разумно) написать тесты и классы Controller перед написанием базовых классов Model? Я думал, что видел заметки о том, как это сделать, но сейчас не могу найти рецепт.
Например, рассмотрим следующий контроллер:
# file: app/controllers/premises_controller.rb
class PremisesController < ApplicationController
def create
@premise = Premise.new(params[:premise])
respond_with @premise
end
end
Могу ли я протестировать этот код контроллера перед созданием базовой модели и помещения Premise? Я знаю, что следующее не сработает - как бы вы переписали это (если это возможно)?
# file: spec/controller/premise_spec.rb
require "spec_helper.rb"
describe PremisesController do
context 'POST create' do
it 'should assign a new Premise to @premise' do
premise = stub_model(Premise)
Premise.stub(:create) { premise }
post :create
assigns(:premise).should == premise
end
end
end
end
Обновить
Чем больше я думаю об этом, тем больше я убежден, что мне нужно определить Premise
класс - PremisesController
Код должен ссылаться на него. Поэтому я изменю свой вопрос на "необходимо ли создавать premises
таблица базы данных для того, чтобы запустить PremisesController
тесты?"
На данный момент, я не вижу хорошего способа обойти это (без изменения PremisesController
код, который побеждает точку тестирования). Например, вызов respond_with
звонки @premise.has_errors?
который, в свою очередь, обращается к базе данных, чтобы получить имена столбцов. Если только я не захочу заглушить внутренние методы ActiveRecord
Я не вижу, как избежать попадания в БД.
Но я бы хотел, чтобы меня показывали иначе.
2 ответа
Хорошо, я смирился с этим: нецелесообразно создавать какие-либо значимые тесты, если таблица базы данных не существует - слишком много битов ActiveRecord зависит от определения таблицы.
Но это не мешает писать тест с чистым разделением между контроллером и моделью. Об этом красноречиво рассказывает Сам Дчелимский в этом выпуске RSpec. Суть его поста:
- Протестируйте с помощью интеграционного теста в spec / запросы /premise_spec.rb, который выдает
get
и проверяет сгенерированный ответ JSON. - При использовании метода тощего контроллера (например, показанного в OP) не беспокойтесь о написании теста контроллера.
- Напишите тесты моделей, чтобы убедиться, что модель испускает правильный json.
Кстати, я действительно рекомендую прочитать пост Дэвида - он проведет вас через пошаговый процесс, объясняя философию и аргументацию каждого шага.
Я еще не тестировал этот код, но уверен, что он должен работать. Вы можете сделать это сейчас: просто для начала, но вы можете попробовать что-то вроде этого, если хотите, хотя, вероятно, плохая практика - изменять ваш код таким образом, чтобы передать спецификации.
class PremisesController < ApplicationController
def create
@premise = premise_until_model_finished params[:premise]
respond_with @premise
end
def premise_until_model_finished premise
Premise.new premise
end
end
require "spec_helper.rb"
describe PremisesController do
context 'when creating a premise' do
before :each do
@my_fake_model = {
:some_attribute => 'funk',
:some_other_attribute => 'a-delic'
}
PremisesController.any_instance.stub( :premise_until_model_finished).and_return(
@my_fake_model
)
PremisesController.any_instance.should_receive(
:premise_until_model_finished
).and_return( @my_fake_model )
post :create
end
it 'should create a premise as expected' do
# your criteria here...
end
end
end