【问题标题】:Rails - How to mock or access methods defined in ApplicationController from helper spec?Rails - 如何从帮助规范中模拟或访问 ApplicationController 中定义的方法?
【发布时间】:2018-02-05 02:48:56
【问题描述】:

我正在尝试为 Rails 助手编写规范。这个助手调用一个方法 在ApplicationController 中定义并通过helper_method 公开:

app/helpers/monkeys_helper.rb

module MonkeysHelper
  def current_monkey_banana_count
    # current_monkey is defined in ApplicationController
    current_monkey.present? ? current_monkey.banana_count : 0 
  end
end

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base   
  helper_method :current_monkey

  protected

  def current_monkey
    @current_monkey ||= Monkey.find(session[:monkey_id])
  end
end

如果我从视图中调用current_monkey_banana_count 并通过浏览器访问它,它可以正常工作。但如果我从这样的规范中调用它:

spec/helpers/monkeys_helper_spec.rb

RSpec.describe MonkeysHelper, type: :helper do
  describe "#current_monkey_banana_count" do
    it "returns 0 if there is no monkey" do
      expect(helper.current_monkey_banana_count).to eq 0
    end
  end
end

然后我在运行规范时收到此错误:

NameError:
       undefined local variable or method `current_monkey' for #<#<Class:0x007fe1ed38d700>:0x007fe1e9c72d88>

Rspec documentation 说:

要访问您指定的辅助方法,只需调用它们 直接在辅助对象上。注意:在中定义的辅助方法 不包括控制器。

知道如何模拟current_monkey 或使其在current_monkey_banana_count 内部可见吗?

谢谢!

【问题讨论】:

    标签: ruby-on-rails rspec


    【解决方案1】:

    也许您可以通过以这种方式模拟current_monkey 来实现这一点(您是否已经尝试过?):

    RSpec.describe MonkeysHelper, type: :helper do
      let(:monkey) { create(:monkey) }
    
      before do
        allow(helper).to receive(:current_monkey_user) { monkey }
      end
    
      # your rest of code
    end
    

    干杯!

    【讨论】:

    • 不幸的是,&lt;Helper ...&gt; does not implement: current_monkey 失败了。显然你不能模拟一个没有定义的方法:(
    【解决方案2】:

    视图可以调用控制器中定义的辅助方法,因为控制器会自动评估它们,请检查代码here

    但是您的辅助测试没有调用控制器,因此current_monkeyMonkeysHelper 模块上不可用。最佳实践是在助手类中定义的控制器调用助手中定义的助手,反之亦然。在您的情况下,您可以将 current_monkey 移动到 MonkeyHelper 以便能够对其进行测试。

    【讨论】:

    • current_monkey 使用了助手中不可用的session 对象,所以我无法将其移至MonkeyHelper
    【解决方案3】:

    我找到了一种(讨厌的)方法,但它确实有效:

    spec/helpers/monkeys_helper_spec.rb:

    require 'rails_helper'
    
    RSpec.describe CartsHelper, type: :helper do
      before do
        def helper.current_monkey; end
      end
    
      describe "#current_monkey_banana_count" do
        it "returns 0 if there is no cart" do
          expect(helper).to receive(:current_monkey).and_return(nil)
          expect(helper.current_monkey_banana_count).to eq 0
        end
    
        it "returns monkey.banana_count if there is a monkey" do
          expect(helper).to receive(:current_monkey).and_return(Monkey.create!(banana_count: 5))
          expect(helper.current_monkey_banana_count).to eq 5
        end
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-19
      • 2011-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多