【问题标题】:Trouble testing controller using rspec and stubs使用 rspec 和存根测试控制器时遇到问题
【发布时间】:2011-06-17 12:12:30
【问题描述】:

我很难使用 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)>'

感谢您的帮助!

【问题讨论】:

  • 删除了我的答案,因为我在阅读时错过了您的一些代码。

标签: ruby-on-rails testing controller rspec rspec2


【解决方案1】:

我没有看到问题,但这里有一个重构建议。如果你发现自己使用了更多的模拟和存根,也许是时候重新考虑你的接口了。在这种情况下,你可以让你的控制器更瘦,你的模型更胖。

# 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

【讨论】:

    【解决方案2】:

    如果你删除@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 页)。

    【讨论】:

    • 谢谢,我听从了你的建议,只是做了一个 flash[:error] 和重定向:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多