Проверка неисправности контроллера с использованием rspec и заглушек - PullRequest
1 голос
/ 17 июня 2011

Мне тяжело тестировать мой контроллер с before_filters, исключениями и некоторыми насмешками и заглушками.Вот контроллер:

before_filter :get_subject, :only => [:show, :edit, :update, :destroy, :update_field]
before_filter :user_has_to_belongs_to_subject_company, :only => [:show, :edit, :update, :destroy, :update_field]

def show
  @messages = @subject.get_user_messages(current_user)
end

private

def get_subject
  @subject = Subject.find(params[:id])
end

def user_has_to_belongs_to_subject_company
  unless @current_user.company.eql?(@subject.company)
    raise "Error: current_user does not belongs to subject's company"
  end
end

И вот мой файл спецификаций:

require 'spec_helper'

describe SubjectsController do  
  describe "for signed users" do
    before(:each) do
      @current_user = Factory(:user)
      sign_in @current_user
    end

    describe "for user belonging to subject's company" do
      before(:each) do
        @subject = mock_model(Subject)  
        Subject.stub!(:find).with(@subject).and_return(@subject)
        @current_user.stub_chain(:company, :eql?).and_return(true)
        @subject.stub!(:company)
      end

      it "should not raise an exception" do
        expect { get :show, :id => @subject }.to_not raise_error
      end
    end

    describe "for user not belonging to subject's company" do
      before(:each) do
        @subject = mock_model(Subject)  
        Subject.stub!(:find).with(@subject).and_return(@subject)
        @current_user.stub_chain(:company, :eql?).and_return(false)
        @subject.stub!(:company)
      end

      it "should raise an exception" do
        expect { get :show, :id => @subject }.to raise_error
      end
    end
  end
end

И, наконец, вот сообщение об ошибке:

SubjectsController for signed users for user belonging to subject's company should not raise an exception
     Failure/Error: expect { get :show, :id => @subject }.to_not raise_error
     expected no Exception, got #<RuntimeError: Error: current_user does not belongs to subject's company>
     # ./spec/controllers/subjects_controller_spec.rb:19:in `block (4 levels) in <top (required)>'

Thx дляпомогает!

Ответы [ 2 ]

1 голос
/ 17 июня 2011

Я не вижу проблемы, но вот предложение по рефакторингу. Если вы обнаружите, что используете больше обычных издевательств и заглушек, возможно, пришло время пересмотреть ваши интерфейсы. В этом случае вы можете сделать свой контроллер стройнее, а модель - толще.

# subjects_controller_spec.rb
describe "for user belonging to subject's company" do
  before(:each) do
    @subject = mock_model(Subject, :verify_user => true)  
    Subject.stub!(:find).with(@subject).and_return(@subject)
  end

# subjects_controller.b
def user_has_to_belongs_to_subject_company
  @subject.verify_user(@current_user)
end

# subject.rb
class Subject
  def verify_user(user)
    unless user.company.eql?(company)
      raise "Error: current_user does not belongs to subject's company"
    end
0 голосов
/ 17 июня 2011

Что произойдет, если вы удалите @ перед @current_user в

def user_has_to_belongs_to_subject_company
  unless @current_user.company.eql?(@subject.company)

чтобы получить

def user_has_to_belongs_to_subject_company
  unless current_user.company.eql?(@subject.company)

А в ваших спецификациях сделайте controller.stub! (: Current_user) .and_return @ current_user

Я думаю, что проблема заключается в области видимости - @current_user в ваших тестах отличается от @current_user в вашем контроллере. Действительно зависит от того, как реализован "sign_in @current_user".

Кроме того, вместо того, чтобы вызвать исключение, возможно, ваш before_filter мог перенаправить пользователя на другую страницу и установить flash [: error]? Фильтр before - правильное место, чтобы справиться с этой ситуацией, поэтому он не должен вызывать исключение, которое пришлось бы спасать где-то еще (или, если нет, он отображал бы 500 страниц пользователю).

...