我正在构建一个Rails应用程序并使用RSpec制定测试。
我为我创建的名为current_link_to
的方法编写了测试。该方法应检查当前页面是否与我传递的路径相对应,并将current
类添加到生成的链接中,以防万一。{/ p>
以下是规范:
require "spec_helper"
describe ApplicationHelper do
describe "#current_link_to" do
let(:name) { "Products" }
let(:path) { products_path }
let(:rendered) { current_link_to(name, path) }
context "when the given path is the current path" do
before { visit(path) }
it "should return a link with the current class" do
# Uses the gem "rspec-html-matchers" (https://github.com/kucaahbe/rspec-html-matchers)
expect(rendered).to have_tag("a", with: { href: path, class: "current" }) do
with_text(name)
end
end
end
context "when the given path is not the current path" do
before { visit(about_path) }
it "should return a link without the current class" do
expect(rendered).to have_tag("a", with: { href: path }, without: { class: "current" } ) do
with_text(name)
end
end
end
end
end
然后我尝试按照规范实现我的方法:
module ApplicationHelper
def current_link_to(name, path, options={})
options.merge!({ class: "#{options[:class]} current".strip }) if current_page?(path)
link_to(name, path, options)
end
end
但是,测试失败并出现以下错误:
Failure/Error: let(:rendered) { current_link_to(name, path) }
RuntimeError: You cannot use helpers that need to determine the current page unless your view context provides a Request object in a #request method
由于我不需要current_page?
辅助方法来对请求执行检查,因此我认为将其存根是有意义的。
我尝试了以下方法,但没有一种方法有效:
helper.double(:current_page? => true)
helper.current_page?
方法,但它与我的函数调用的方法不同。allow(ActionView::Helpers::UrlHelper).to receive(:current_page?).and_return(true)
在撰写此问题时我偶然发现了解决方案。我设法在current_page?
块中使用此方法存根before
方法:
allow(self).to receive(:current_page?).and_return(true)
它有效,但是这个解决方案提出的问题多于它真正回答的问题。我现在对这是如何工作感到困惑,因为self
中的before
似乎很奇怪block会响应current_page?
,并且所述方法实际上与我的助手调用的方法完全相同。
即使在阅读文档并试图通过puts
来电乱丢我的代码来弄清楚其工作原理之后,以下疑惑仍然困扰着我:
helper
对象的方法提供?current_page?
块中对self
上的before
方法进行存根,以某种方式反映出我的助手调用的实际方法?出于某种原因,我的助手中的self
是否会引用您在self
区块中找到的before
? RSpec或Rails包括和混合物吗?self
包含我的规范和帮助者,那么self
在这种情况下究竟是指什么,为什么它在任何地方都一样?如果有人可以帮我解决这个问题会很好,因为这让我大吃一惊,而且我害怕使用我不太懂的代码。
答案 0 :(得分:0)
尊敬的是,你在这里测试的功能太多了。诀窍是只测试你需要测试的位。
在这种情况下,您只需要测试当前类是否在需要时添加,而不是在不需要时添加。
这段代码可以帮到你:
require 'rails_helper'
# Specs in this file have access to a helper object that includes
# the ApplicationHelper.
RSpec.describe ApplicationHelper, type: :helper do
describe 'current_link_to' do
let(:subject) { helper.current_link_to('some_name', 'some_path', options = {}) }
context 'where the path is current' do
before do
allow(helper).to receive(:current_page?).and_return true
end
it 'should include the current class' do
expect(subject).to match /current/
end
end
context 'where the path is not current' do
before do
allow(helper).to receive(:current_page?).and_return false
end
it 'should not include the current class' do
expect(subject).to_not match /current/
end
end
end
end
我一直有点滑稽,只测试返回字符串中'current'的存在。如果你想更精确,可以测试'class =“current”'之类的东西。
另一个关键是页面顶部的注释,Rails会为您插入空白帮助器规范:
# Specs in this file have access to a helper object that includes
# the ApplicationHelper.
这意味着你可以使用'helper'在你的评论中使用'self',这会让事情变得更加清晰(imho)
希望它有所帮助!