Ruby on rails 3 将控制器测试与模型隔离

Ruby on rails 3 将控制器测试与模型隔离,ruby-on-rails-3,mocking,rspec2,stubbing,Ruby On Rails 3,Mocking,Rspec2,Stubbing,在编写底层模型类之前编写控制器测试和类是否可能(并且合理)?我以为我看到了关于如何做的说明,但现在我找不到配方 例如,考虑下面的控制器: # file: app/controllers/premises_controller.rb class PremisesController < ApplicationController def create @premise = Premise.new(params[:premise]) respond_with @premi

在编写底层模型类之前编写控制器测试和类是否可能(并且合理)?我以为我看到了关于如何做的说明,但现在我找不到配方

例如,考虑下面的控制器:

# file: app/controllers/premises_controller.rb
class PremisesController < ApplicationController

  def create
    @premise = Premise.new(params[:premise])
    respond_with @premise
  end

end
更新 我想得越多,就越确信我确实需要定义
PremisesController
类--
PremisesController
代码需要引用它。因此,我将问题改为“是否需要创建底层
PremisesController
数据库表以运行
PremisesController
测试?”

在这一点上,我看不到一个好的解决方法(如果不更改
PremisesController
code,这会破坏测试的意义)。例如,调用
respond\u with
调用
@premise.has\u errors?
,然后访问数据库获取列名。除非我愿意在
ActiveRecord
内部存根方法,否则我不知道如何避免对数据库的攻击


但我希望能有其他的表现。

我还没有测试过这段代码,但我很确定它应该可以工作。您现在可以这样做: 这只是一个开始,但如果您愿意,可以尝试类似的方法,尽管像这样更改代码只是为了通过规范可能是不好的做法

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
class PremisesController'funk',
:some_other_属性=>'a-delic'
}
PremisesController.any_instance.stub(:premise_直到_model_完成)。然后返回(
@我的假模型
)
PremisesController。任何\u实例。是否应\u接收(
:前提\u直到\u模型\u完成
).和_return(@my_fake_model)
帖子:创建
结束
它“应该像预期的那样创建一个前提”
#你的标准在这里。。。
结束
结束
结束

好的-我已经平静下来了:除非数据库表存在,否则创建任何有意义的测试是不现实的——太多的ActiveRecord位取决于定义了表

但这并不妨碍在控制器和模型之间明确分离的情况下编写测试。这是德切利姆斯基本人在本书中雄辩地阐述的。他这篇文章的要点是:

  • 使用spec/requests/premise_spec.rb中的集成测试进行测试,该测试发出
    get
    ,并验证生成的json响应
  • 使用瘦控制器方法(如OP中所示),无需费心编写控制器测试
  • 编写模型测试以验证模型是否发出正确的json

顺便说一句,我真的建议你阅读大卫的帖子——他会带你一步一步地走,解释每一步背后的哲学和推理。

+1供funkadelic参考。但是我同意您(强调)的观点,修改生产代码以通过测试首先否定了测试的意义。
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