Тестирование изоляции контроллера от моделей

Возможно ли (и разумно) написать тесты и классы 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
Другие вопросы по тегам