Rails 5 功能测试(Rspec/Devise 冲突?NoMethodError: 未定义的方法管理员?对于 #<用户



我正在通过轨道课程工作,试图测试我的应用程序。我遇到了一个问题,似乎表明RSPEC没有使用它与Devise(Cancancan)一起使用的助手。

链接到下面的回购。我是一个相当新的开发人员,但努力使其可读。谢谢,所有的反馈都感谢。

问题来自我的users_controller_spec.rb文件:

Failures:
  1) UsersController GET #show User is logged in loads correct user details
 Failure/Error: if user&.admin?
 NoMethodError:
   undefined method `admin?' for #<User:0x00000005c08eb0>
 # ./app/models/ability.rb:14:in `initialize'
 # /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/cancancan-1.15.0/lib/cancan/controller_additions.rb:361:in `new'
 # /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/cancancan-1.15.0/lib/cancan/controller_additions.rb:361:in `current_ability'
 # /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/cancancan-1.15.0/lib/cancan/controller_additions.rb:342:in `authorize!'
 # /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/cancancan-1.15.0/lib/cancan/controller_resource.rb:49:in `authorize_resource'
 # /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/cancancan-1.15.0/lib/cancan/controller_resource.rb:34:in `load_and_authorize_resource'
 # /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/cancancan-1.15.0/lib/cancan/controller_resource.rb:10:in `block in add_before_action'
 # /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/rails-controller-testing-1.0.1/lib/rails/controller/testing/template_assertions.rb:61:in `process'
 # /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:33:in `block in process'
 # /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:100:in `catch'
 # /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:100:in `_catch_warden'
 # /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:33:in `process'
 # /home/scorpian55/.rvm/gems/ruby-2.3.1@unit4-1/gems/rails-controller-testing-1.0.1/lib/rails/controller/testing/integration.rb:12:in `block (2 levels) in <module:Integration>'
 # ./spec/controllers/users_controller_spec.rb:15:in `block (4 levels) in <top (required)>'
Finished in 0.36791 seconds (files took 4.43 seconds to load)
7 examples, 1 failure
Failed examples:
rspec ./spec/controllers/users_controller_spec.rb:14 # UsersController GET #show User is logged in loads correct user details

在研究中,我见过的大多数错误都在nil:nil:nilclass和我没有遇到的错误,这是一个不同的问题,而不是完全相同的错误消息。

,这是一个不同的问题。

我已经检查了:

1)spec/rails_helper.rb具有:

config.include Devise::Test::ControllerHelpers, :type => :controller

2)spec/spec_helper.rb具有:

require 'spec_helper'
require 'rspec/rails'
# note: require 'devise' after require 'rspec/rails'
require 'devise'
RSpec.configure do |config|
  config.include Devise::Test::ControllerHelpers, :type => :controller
end

per:https://github.com/plataformatec/devise/wiki/wiki/how-to:test-controllers-with-rails-3-and-4-->>

这是相关文件(以及我的回复:https://github.com/scorpian5555/gitwork):

users_controller_spec.rb

 require 'rails_helper'
describe UsersController, :type => :controller do
let(:user) { User.create!(email: "user#{rand(100000).to_s}@examples.com", password: '1234567890') }
  describe 'GET #show' do
 context 'User is logged in' do
  before do
    sign_in user
  end
  it 'loads correct user details' do
    get :show, id: user.id
    expect(response).to have_http_status(200)
    expect(assigns(:user)).to eq user
  end
end #end of first context
 context 'No user is logged in' do
   it 'redirects to login' do
     get :show, id: user.id
     expect(response).to redirect_to(new_user_session_path)
   end
 end
  end #end of GET#show block
end #end of whole block

能力.rb:

class Ability
  include CanCan::Ability
  def initialize(user)
# Define abilities for the passed in user here. For example:
#
 user ||= User.new # guest user (not logged in)
 alias_action :create, :read, :update, :destroy, to: :crud
 can :manage, User, id: user.id
  if user&.admin?
    can :crud, Product
    can :crud, User
    can :crud, Comment
   elsif user&.signed_in?
    can :read, Comment
    can :create, Comment
    can :read, Product
    #can :invite, :User
  else
    can :read, Comment
    can :read, Product
   end #end if/else
  end #end def initialize(user)
end  #end class Ability

users_controller.rb:

  class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user!
  load_and_authorize_resource
  # GET /users
  # GET /users.json
  def index
    @users = User.all
  end
  # GET /users/1
  # GET /users/1.json
  def show
  end
  # GET /users/new
  def new
    @user = User.new
  end
  # GET /users/1/edit
  def edit
  end
  #  POST /users
  # POST /users.json
  def create
    @user = User.new(user_params)
    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: 'User was     successfully created.' }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new }
    format.json { render json: @user.errors, status: :unprocessable_entity }
  end
end
  end
  # PATCH/PUT /users/1
  # PATCH/PUT /users/1.json
  def update
respond_to do |format|
  if @user.update(user_params)
    format.html { redirect_to @user, notice: 'User was successfully updated.' }
    format.json { render :show, status: :ok, location: @user }
  else
    format.html { render :edit }
    format.json { render json: @user.errors, status: :unprocessable_entity }
  end
end
  end
  # DELETE /users/1
  # DELETE /users/1.json
  def destroy
    @user.destroy
    respond_to do |format|
      format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
      format.json { head :no_content }
    end
  end
  private
    # Use callbacks to share common setup or constraints between actions.
def set_user
  @user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
  params.require(:user).permit(:first_name, :last_name)
end
end

schema.db

ActiveRecord::Schema.define(version: 20161219012011) do
  create_table "comments", force: :cascade do |t|
t.integer  "user_id"
t.text     "body"
t.integer  "rating"
t.integer  "product_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["product_id"], name: "index_comments_on_product_id"
t.index ["user_id"], name: "index_comments_on_user_id"
  end
  create_table "orders", force: :cascade do |t|
t.integer "user_id"
t.integer "product_id"
t.float   "total"
t.index ["product_id"], name: "index_orders_on_product_id"
t.index ["user_id"], name: "index_orders_on_user_id"
  end
  create_table "products", force: :cascade do |t|
t.string   "name"
t.text     "description"
t.string   "image_url"
t.datetime "created_at",  null: false
t.datetime "updated_at",  null: false
t.string   "color"
t.decimal  "price"
  end
  create_table "users", force: :cascade do |t|
t.string   "first_name"
t.string   "last_name"
t.datetime "created_at",                          null: false
t.datetime "updated_at",                          null: false
t.string   "email",                  default: "", null: false
t.string   "encrypted_password",     default: "", null: false
t.string   "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer  "sign_in_count",          default: 0,  null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string   "current_sign_in_ip"
t.string   "last_sign_in_ip"
t.boolean  "admin",                  default: false, null: false
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

user.rb

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  has_many :orders
  has_many :comments  #added troubleshooting 6.3, need to test
end

您的代码没有明显的错误,因此我检索了您的回购,安装了宝石并运行DB:设置:我发现我复制了您的错误。

我不确定您在问题中发布的架构在哪里,但这不是您的数据库使用的模式。存储库中的一个没有管理员布尔值:

  create_table "users", force: :cascade do |t|
    t.string   "first_name"
    t.string   "last_name"
    t.datetime "created_at",                             null: false
    t.datetime "updated_at",                             null: false
    t.string   "email",                  default: "",    null: false
    t.string   "encrypted_password",     default: "",    null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,     null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

我确实注意到您确实有一个迁移来添加该列。不知何故,您的迁移和模式已经不同步(可能在运行迁移后恢复到以前的模式)。最好的办法是重新创建添加该列的迁移:

rails g migration add_admin_flag_to_users --force

编辑迁移并添加以下内容:

add_column :users, :admin, :boolean, default: false, null: false

运行rails db:migraterails db:migrate RAILS_ENV=test

现在有效以下工作:

$ rails c
Running via Spring preloader in process 60107
Loading development environment (Rails 5.0.0.1)
2.3.1 :001 > user = User.new
 => #<User id: nil, first_name: nil, last_name: nil, created_at: nil, updated_at: nil, email: "", admin: false>
2.3.1 :002 > user.admin?
 => false
2.3.1 :003 >

Note 您的测试仍然会在验证上失败,但这是一个完全独立的问题,并且您已经通过了此障碍,可以调查一个问题:)

顺便说一句,在您的研究中,您遇到了nil nil类的nomethoderror,您的代码受到保护:

user&.admin?

&字符基本上是在说如果用户不是零,相当于:

user.admin? if user

相关内容

最新更新