【问题标题】:Accessing session from a helper spec in rspec从 rspec 中的帮助规范访问会话
【发布时间】:2012-12-02 20:42:31
【问题描述】:

我的 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:

通过调试,我看到 session 正在从 @request.session 在 ActionDispatch::TestProcess 中访问,而 @request 为零。当我从我的请求规范访问会话时,@request 是 ActionController::TestRequest 的一个实例。

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

****更新****

这要归功于我的工厂中有include ActionDispatch::TestProcess。删除此包含可以解决问题。

【问题讨论】:

标签: ruby-on-rails ruby rspec tdd


【解决方案1】:

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

是的。

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 通常表示递归出错了。

【讨论】:

  • 不幸的是,这也给出了相同的堆栈太深的错误。调试递归转到 ActionDispatch::TestProcess 中的会话方法,该方法调用 @request.session 和 @request 为零。 @request.session 似乎在 ActionDispatch::TestProcess 上调用 session ,所以这个循环直到堆栈太深。由此我认为我需要以某种方式将会话注入助手,但我似乎无法弄清楚如何。
  • 我在答案中运行了代码,得到了空哈希作为输出。这表明您的环境可能有问题。我会尝试将一个干净的 Rails 安装到一个新项目中,看看问题是否仍然存在。
  • 好的,所以经过一些实验后,我发现导致我头痛的是factory_girl_rails gem,这很烦人,因为我有数百个使用它的测试。我要去看看是否有任何修复它,否则看起来我将不得不寻找工厂女孩的替代品。感谢您为我指明正确的方向。
  • 进一步检查表明,我的工厂中有include ActionDispatch::TestProcess,因为我使用fixture_file_upload 在我的模型中包含测试图像。因为我实际上并没有使用这些,所以我已经删除了它们。呸!
【解决方案2】:

您正在测试 has_basket_items? ApplicationHelper 中的操作,它检查篮子表中带有 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 的更多详细信息

它将在您的测试数据库中创建一个工厂对象。所以,基本上你可以创建一些工厂对象,然后在 session 中设置一个 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 是否为真:

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

【讨论】:

  • 我已经尝试过您的建议,但不幸的是我得到了相同的结果。据我所知,这似乎更多是因为请求对象没有被注入到我的助手中,而不是数据库中不存在对象。事实上,我的方法不应该存在任何篮子实体。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多