0

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

例如,考虑以下控制器:

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

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

end

我可以在创建基础前提模型和前提之前测试此控制器代码吗?我知道以下内容行不通——你将如何重写它(如果可能的话)?

# 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,否则我看不到如何避免对数据库的影响。

但我很乐意以其他方式展示。

4

2 回答 2

0

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

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
于 2012-03-31T02:28:23.507 回答
0

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

但这并不妨碍编写测试,控制器和模型之间有一个干净的分离。dchelimsky 本人在此 RSpec 问题中雄辩地介绍了这一点。他的帖子的要点:

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

顺便说一句,我真的建议您阅读 David 的帖子——他将带您逐步完成过程,解释每一步背后的理念和推理。

于 2012-04-01T17:52:31.173 回答