RSpec控制器规范:任何确保控制器实例变量不会在多个'gets'之间交叉的方法

时间:2013-01-04 02:36:51

标签: rspec

如果我们必须在同一规范上下文中进行多次获取,那么控制器规范中是否有任何方法可以在每次获取之前“重置”实例变量空间?

我理解每个测试的一个断言指南。但是,对于我们的一组测试,如果我们在每次获取之前不进行单独的(冗长的)before(:each)设置,并且如果我们在一个上下文中一起运行一系列get / asserts,则运行速度提高约3倍

然而,似乎(与通过浏览器调用控制器方法不同)如果使用rspec连续两次获取,则每次获取都不会清除实例变量,因此可以进行数据交叉。

这是一个失败的测试,显示当另一个控制器方法'vartest2'运行时,'vartest1'中设置的变量仍然存在:

控制器方法:

  def vartest1
    @this_var = "foo" 
    render :text => @this_var
  end

  def vartest2
    render :text => @this_var # should be EMPTY!
  end

Rspec控制器规范:

  describe "instance variable crossover example", :focus => true do
    describe "THIS PASSES put each get in separate contexts" do
      it "vartest1 outputs foo" do
        get "vartest1"
        response.body.should include("foo")
      end
      it "vartest2 does NOT output foo" do
        get "vartest2"
        response.body.should_not include("foo")
      end
    end
    describe "THIS FAILS put both gets in SAME context" do
      it "should not crossover controller instance varables" do
        get "vartest1"
        response.body.should include("foo")
        get "vartest2"
        response.body.should_not include("foo") # THIS FAILS
      end
    end
  end

Rspec结果:

 instance variable crossover example
    THIS PASSES put each get in separate contexts
      vartest1 outputs foo
      vartest2 does NOT output foo
    THIS FAILS put both gets in SAME context
      should not crossover controller instance varables (FAILED - 1)

失败测试中发生的事情是,当rspec执行get 'vartest1'时,控制器方法将实例变量设置为'foo',而当rspec执行get 'vartest2'时,实例变量(应该为nil)是仍然设置,所以测试失败。

1 个答案:

答案 0 :(得分:4)

控制器规格是单元测试。像所有单元测试一样,它们应该单独测试方法。对于控制器,这意味着每个操作都需要自己的规范。在控制器规范中执行多个请求不太可能让你到任何地方。

您可以考虑使用请求规范或黄瓜。根据您的环境,这可能会获得更好的结果,因为每个示例只需要进行一次设置。然后,您可以执行多个gets(或visits)。

另一种可能性是使用模拟/存根来实现控制器规格。这可以显着提高性能,但需要进行额外设置。控制器规格的RSpec脚手架示例是这种方法的一个很好的起点。