我有一个基于MHartl的RoR4 Tutorial
的控制器就像MHartl一样,我没有使用Devise ,我rolled my own authentication system
由于视图调用UsersController#Edit
且控制器调用current_user.admin?
@path_switch = path_switch
的RSpec出现问题
我不断得到RSpec错误:
1) User Pages Edit
Failure/Error: visit edit_user_path(user)
NoMethodError:
undefined method `admin?' for nil:NilClass
# ./app/controllers/users_controller.rb:106:in `path_switch'
# ./app/controllers/users_controller.rb:53:in `edit'
# ./spec/requests/user_pages_spec.rb:54:in `block (3 levels) in <top (required)>'
UsersController:
class UsersController < ApplicationController
...
def edit
@user = User.find(params[:id])
@path_switch ||= path_switch #error
end
...
def path_switch
if current_user.admin? #error
users_path
else
root_path
end
end
end
我发现这个really helpful article让我希望自己走上正轨,但我无法让它发挥作用。
据我所知(已更新):
user_pages_spec.rb:
require 'spec_helper'
require 'support/utilities'
describe "User Pages" do
#include SessionsHelper
let(:user) { FactoryGirl.create(:user) }
let(:current_user) {user}
subject { page }
describe "Edit" do
before do
sign_in(user)
visit edit_user_path(user)
end
it '(check links and content)' do
should have_button('Submit')
should have_link('Cancel')
should have_content(user.fname+"\'s profile")
end
...
end
...
end
但current_user
仍然会回来nil
感谢任何帮助/指导。谢谢!
将include SessionsHelper
添加到我的user_pages_edit.rb
的顶部描述块似乎尝试使用该帮助程序中的sign_in(路径)。创建issue between RSpec and cookies.permanent
。所以这是一个破产。
很遗憾,这让我回到.admin?
错误。
有两次拨打current_user.admin?
一个在控制器中:
def path_switch
if current_user.admin? #error current_user == nil
users_path
else
root_path
end
end
其中一个是ERB:
<% if current_user.admin? %>
<div class="row col-xs-6 col-sm-6 col-md-3">
<div class="input-group input-selector">
...
我需要做的就是弄清楚如何设置current_user.admin = true
并将其传递给控制器(然后希望视图),以便页面可以加载。
要做到这一点,我需要做的就是设置current_user = user
,因为user.admin == true
。
答案 0 :(得分:34)
如果你正在进行控制器的单元测试,你可以简单地将current_user
存储在之前的块中,如下所示:
let(:user) { ... }
# RSpec version <= 2 syntax:
before { controller.stub(:current_user) { user } }
# RSpec version >= 3 syntax:
before { allow(controller).to receive(:current_user) { user } }
如果您正在执行功能或请求测试,我建议您通过在数据库中创建用户,然后使用此用户凭据传递您的登录页面来执行真正的登录/ p>
在这里,您似乎正在进行功能测试,您应该编写一个帮助程序来执行用户记录的创建并完成登录。
此外,在功能测试中,为了在运行测试时获得大量时间,请不要犹豫,将断言分组到同一个块中。显然,而不是:
it { should have_button('Submit')}
it { should have_link('Cancel')}
it { should have_content(user.fname+"\'s profile")}
你可以写
it 'check links and content' do
should have_button('Submit')
should have_link('Cancel')
should have_content(user.fname+"\'s profile")
end
这样可以避免生成多个会话的功能环境,也可以多次登录
答案 1 :(得分:1)
也有效
user = create(:user) #FactoryGirl
allow(controller).to receive(:current_user).and_return(user)
答案 2 :(得分:0)
对我而言,与之合作:
before { controller.stub!(:current_user).and_return(user) }
答案 3 :(得分:0)
我在使用旧版Rails 4应用程序时遇到了同样的问题,并且我的解决方案基于Rspec Views的this测试用例。
首先定义一个助手,它将在控制器实例中定义缺少的助手方法
# /spec/support/concerns/view_helper.rb
module ViewHelper
def include_current_user_helper(&block)
controller.singleton_class.class_eval do
define_method :current_user, &block
helper_method :current_user
end
end
end
然后配置Rspec使其包含在所有视图助手中
# spec/rails_helper.rb
# ...
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
RSpec.configure do |config|
# ...
config.include ViewHelper, type: :view
end
在视图规范中,它被称为
RSpec.describe 'something' do
let!(:user) { FactoryGirl.create(:user) } # Note the "!" there
before { include_current_user_helper { user } }
# do stuff
end
注意:用爆炸声来调用let
很重要,因为该块内的内容将在测试范围之外被延迟执行,否则用户将零落