从rspec中的帮助程序规范访问会话

时间:2012-12-02 20:42:32

标签: ruby-on-rails ruby rspec tdd

我的ApplicationHelper中有一个方法可以检查我的购物篮中是否有任何商品

module ApplicationHelper
  def has_basket_items?
    basket = Basket.find(session[:basket_id])
    basket ? !basket.basket_items.empty? : false
  end
end

这是我的帮助规范,我必须对此进行测试:

require 'spec_helper'

describe ApplicationHelper do
  describe 'has_basket_items?' do
    describe 'with no basket' do

      it "should return false" do
        helper.has_basket_items?.should be_false
      end

    end
  end
end

然而,当我运行测试时,我得到了

SystemStackError: stack level too deep
/home/user/.rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.2.8/lib/action_dispatch/testing/test_process.rb:13:

从调试开始,我看到会话正在来自@ request.session的ActionDispatch :: TestProcess中访问,而@request是nil。当我从我的请求访问会话时,规范@request是ActionController :: TestRequest的实例。

我的问题是我可以从帮助程序规范访问会话对象吗?如果我可以,怎么样?如果我不能测试这种方法的最佳实践是什么?

**** 更新 * ***

这归结于我的工厂include ActionDispatch::TestProcess。删除此选项包括对问题进行排序。

2 个答案:

答案 0 :(得分:3)

我可以从帮助程序规范中访问会话对象吗?

module ApplicationHelper
  def has_basket_items?
    raise session.inspect
    basket = Basket.find(session[:basket_id])
    basket ? !basket.basket_items.empty? : false
  end
end

$ rspec spec/helpers/application_helper.rb

Failure/Error: helper.has_basket_items?.should be_false
  RuntimeError:
    {}

会话对象在那里并返回一个空哈希。

尝试更详细地查看回溯以查找错误。 stack level too deep通常表示递归出错。

答案 1 :(得分:2)

您正在测试has_basket_items? ApplicationHelper中的操作,它使用baskets表中的basket_id检查特定的篮子,因此您的测试中应该有一些篮子对象,您可以使用Factory_Girl gem创建。

她是一个例子: -

basket1 = Factory(:basket, :name => 'basket_1')
basket2 = Factory(:basket, :name => 'basket_2')

您可以从此屏幕投射http://railscasts.com/episodes/158-factories-not-fixtures

获取有关如何使用factory_girl的更多详细信息

它将在您的测试数据库中创建一个Factory对象。所以,基本上你可以创建一些工厂对象然后在会话中设置一个basket_id来检查它的存在,如下所示:

session[:basket_id] = basket1.id

所以,你的测试应该是这样的: -

require 'spec_helper'

describe ApplicationHelper do
  describe 'has_basket_items?' do
    describe 'with no basket' do

      it "should return false" do
        basket1 = Factory(:basket, :name => 'basket_1')
        basket2 = Factory(:basket, :name => 'basket_2')
        session[:basket_id] = 1234 # a random basket_id 
        helper.has_basket_items?.should be_false
      end

    end
  end
end

或者,您可以使用以下命令检查factory_girl创建的basket_id是否为be_true:

session[:basket_id] = basket1.id
helper.has_basket_items?.should be_true