【问题标题】:Why does my test return a nil class error on an attribute it shouldn't?为什么我的测试在它不应该返回的属性上返回 nil 类错误?
【发布时间】:2015-10-20 06:08:19
【问题描述】:

我正在尝试为我的InvitationsController#Create 编写测试。

这是一个POST http 操作。

基本上应该发生的事情是,一旦post#create第一次执行,我们需要做的第一件事是检查系统中是否存在User,用于通过params[:email]传入的电子邮件在Post 请求上。

我很难弄清楚我是如何做到这一点的。

我稍后会重构,但首先我想让测试功能正常工作。

这就是我所拥有的:

describe 'POST #create' do
    context 'when invited user IS an existing user' do
        before :each do
          @users =  [
            attributes_for(:user),
            attributes_for(:user),
            attributes_for(:user)
          ]
        end

       it 'correctly finds User record of invited user' do
          post :create, { email: @users.first[:email] }
          expect(response).to include(@users.first[:email])
        end
    end
end

这是我得到的错误:

 1) Users::InvitationsController POST #create when invited user IS an existing user correctly finds User record of invited user
     Failure/Error: post :create, { email: @users.first[:email] }
     NoMethodError:
       undefined method `name' for nil:NilClass

 #@myapp/gems/devise-3.2.4/app/controllers/devise_controller.rb:22:in 'resource_name'
 # @myapp/gems/devise_invitable-1.3.6/lib/devise_invitable/controllers/helpers.rb:18:in 'authenticate_inviter!'
 # @myapp/gems/devise_invitable-1.3.6/app/controllers/devise/invitations_controller.rb:67:in 'current_inviter'
 # @myapp/gems/devise_invitable-1.3.6/app/controllers/devise/invitations_controller.rb:71:in 'has_invitations_left?'

我正在使用 FactoryGirl,它运行良好,因为它返回所有数据类型的有效数据。这里的问题是如何让 RSpec 实际测试我需要的功能。

编辑 1

添加了我的:user工厂:

FactoryGirl.define do
  factory :user do
    association :family_tree
    first_name { Faker::Name.first_name }
    last_name { Faker::Name.last_name }
    email { Faker::Internet.email }
    password "password123"
    password_confirmation "password123"
    bio { Faker::Lorem.paragraph }
    invitation_relation { Faker::Lorem.word }
    # required if the Devise Confirmable module is used
    confirmed_at Time.now
    gender 1
  end
end

【问题讨论】:

  • 也许是个愚蠢的问题,但您是否创建了一个名为 :user 的 Rspec 工厂?您可以尝试不使用 :each -> before do。问题来自您的before。如果:userFactoryGirl 模型,你应该这样称呼它:FactoryGirl.create(:user)
  • 是的,我确实创建了一个名为 :user 的工厂。您可以使用一些方法作为速记(例如create, attributes_for, build 等)。我在before 块中使用create 进行了尝试,但我仍然遇到这个问题。 github.com/thoughtbot/factory_girl/blob/master/…
  • 可以加你:user工厂吗?在您的devise_controller 的第 22 行附近? :)
  • 我添加了我的:user 工厂。我没有devise_controller。那是 stock devise gem 中的控制器。
  • @bobbystouket - 我认为这是它在 devise_controller gem 中所指的行 - github.com/plataformatec/devise/blob/v3.2/app/controllers/…

标签: ruby-on-rails ruby-on-rails-4 rspec rspec3


【解决方案1】:

您似乎正在使用Devise,这要求您在进行下一步之前先登录。在您的错误中,Devise 无法与您的inviter 相同,因为他没有登录。

你的测试应该是这样的:

describe 'POST #create' do
    context 'when invited user IS an existing user' do
      before :each do
        @users =  [
          attributes_for(:user),
          attributes_for(:user),
          attributes_for(:user)
        ]
        @another_user = FactoryGirl.create(:user_for_login)
        sign_in @another_user
      end

      it 'correctly finds User record of invited user' do
        post :create, { email: @users.first[:email] }
        expect(response).to include(@users.first[:email])
      end
   end
end

FactoryGirlDevise 的模型示例

factory :user_for_login, class: User do |u|
  u.email 'admin@myawesomeapp.com'
  u.password 'password'
  u.password_confirmation 'password'
  u.name "MyName"
end

当然,您需要添加尽可能多的验证器所需的数据。基本上对于Devise,您需要emailpasswordpassword_confirmation。在您的情况下,您似乎还需要name

【讨论】:

  • :user_for_login的工厂应该是什么样子的?
  • 好的,我让工厂工作了,我只是使用了现有的常规 :user 工厂。但现在我仍然收到undefined method 'name' for nil:NilClass 错误。
  • 你登录你的用户了吗?
  • 我添加了一个工厂示例。创建后,您需要使用sign_in @another_user。然后你可以调用你的POST 方法。
  • 好的,我刚刚尝试过,现在出现此错误:Failure/Error: @another_user = create(:user_for_login) NoMethodError: undefined method 'name=' for #<User:0x007ff4de644080>。当我摆脱 FG 模型中的 u.name 属性时,它给了我与以前相同的 name nil 错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-03
  • 1970-01-01
  • 2017-03-13
  • 2020-12-14
  • 1970-01-01
  • 2017-11-25
相关资源
最近更新 更多