【问题标题】:Rails testing with rspec使用 rspec 进行 Rails 测试
【发布时间】:2018-03-15 17:49:43
【问题描述】:

我在使用 rspec 在 Rails 中进行测试时遇到问题。总而言之,我有 4 个模型之间的结构,但目前我尝试解决其中两个模型的测试。我正在使用 faker 和 FactoryGirl 并拥有以下工厂:

 require 'faker'

 FactoryGirl.define do
   factory :user do |f|
     f.name { Faker::Name}
     f.email { Faker::Internet.email}
     f.password {Faker::Internet.password}
     f.role {"Kindergarten"}
   end
 end




 require 'faker'

 FactoryGirl.define do
   factory :child do |f|
     f.name { Faker::Name}
     f.city { Faker::Address.city}
     f.postalcode {Faker::Number.between(30000,35000)}
     f.streed {Faker::Address.street_name}
     f.add_number {Faker::Address.secondary_address}
     f.disability { Faker::Boolean.boolean}
     f.halal { Faker::Boolean.boolean}
     f.koscha {Faker::Boolean.boolean}
     f.vegetarian {Faker::Boolean.boolean}
     f.vegan {Faker::Boolean.boolean}
     f.allday { Faker::Boolean.boolean}
     f.gender { Faker::Number.between(0,1)}
     f.user_id {Faker::Number.between(1,10)}
   end
 end

我的控制器测试看起来像这样

 require 'rails_helper'
 require 'factory_girl_rails'

 describe UsersController do

   before do
     3.times { FactoryGirl.create(:child)}
   end

   describe "GET #show" do
     let(:user) { FactoryGirl.create(:user) }
     before { get :show, id: user.id}
     it "assigns the requested user to @user" do
       assigns(:user).should eq user
     end
     it "renders  the :show template"
   end

   describe "GET #new" do
     let(:user) { FactoryGirl.create(:user) }
     it "assigns a new User to @user" do
       get :new, id: user.id
       assigns(:user).should be_a_new(User)
     end
     it "renders  the :new template"
   end

 end

当我尝试运行测试时,我收到此错误消息

  UsersController GET #new assigns a new User to @user
      Failure/Error: 3.times { FactoryGirl.create(:child)}

      ActiveRecord::RecordInvalid:
        Validation failed: User can't be blank

我在模型中的关系和验证如下

 class Child < ApplicationRecord

   has_many :relations, :dependent => :destroy
   accepts_nested_attributes_for :relations
   belongs_to :user
   validates :user, presence: true
   validates :name, presence: true, length: { maximum: 50 }
   validates :city, presence: true, :on => :create
     validates :postalcode, presence: true, numericality: true
       validates :streed, presence: true
         validates :add_number, presence: true

 validates :disability, inclusion: { in: [true, false] }
 validates :halal, inclusion: { in: [true, false] }
 validates :koscha, inclusion: { in: [true, false] }
 validates :vegetarian, inclusion: { in: [true, false] }
 validates :vegan, inclusion: { in: [true, false] }
 validates :allday, inclusion: { in: [true, false] }

 validates :gender, presence: true

 end


 class User < ApplicationRecord
   attr_accessor :remember_token, :activation_token, :reset_token
   has_many :children, dependent: :destroy
   has_many :kindergartens, dependent: :destroy
   has_many :relations, dependent: :destroy
   before_save   :downcase_email
   before_create :create_activation_digest
   validates :name, presence: true, length: { maximum: 50 }
   VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
   validates :email, presence: true, length: { maximum: 255 },
                     format: { with: VALID_EMAIL_REGEX },
                     uniqueness: { case_sensitive: false }

 validates :role, presence: true


   has_secure_password
   validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
 end

我的问题是,我不确定我的 rspec 代码是否存在错误,或者我的正常模型中的验证和关系是否存在错误。有人可以帮我吗?

【问题讨论】:

  • 在子工厂中,f.user_id 应该引用现有的用户记录。目前不是,这会在创建子项时引发此空白错误。使用 f.assocation(:user, :factory =&gt; :user) 而不是 f.user_id 行。如果您的测试套件不需要 Child 对象具有关联的 User 记录,则可以仅针对此测试上下文模拟 Childuser 方法,从而节省一些性能
  • 顺便说一句,FactoryGirl.create_list(:factory_name, 3)3.times { create(:factory_name) } 更有效
  • @MrYoshiji 你应该把这个留作 ann annswer
  • 感谢您的帮助。我已经像你说的那样尝试了替换 f.user_id 行,但是我得到了一个新错误,参数数量错误 Failure/Error: f.assocation(:user, : factory => :user) {Faker::Number.between(1,10)} ArgumentError:参数数量错误(给定 3,预期 1..2)
  • 你可以直接说association :user,甚至可以直接说user

标签: ruby-on-rails ruby rspec-rails faker


【解决方案1】:

我认为最好为您发布整个工厂。如果你在 Gemfile 中有它,我认为你不需要 require faker

FactoryGirl.define do
  factory :child do 
    name { Faker::Name}
    city { Faker::Address.city}
    postalcode {Faker::Number.between(30000,35000)}
    streed {Faker::Address.street_name}
    add_number {Faker::Address.secondary_address}
    disability { Faker::Boolean.boolean}
    halal { Faker::Boolean.boolean}
    koscha {Faker::Boolean.boolean}
    vegetarian {Faker::Boolean.boolean}
    vegan {Faker::Boolean.boolean}
    allday { Faker::Boolean.boolean}
    gender { Faker::Number.between(0,1)}
    user
  end
end

当您需要为特定用户创建孩子时的内部规范:

let(:current_user) { create :user }
let(:child) { create :child, user: current_user }

尝试更改您的控制器规格:

 describe UsersController do
   let(:user) { create(:user) }

   describe "GET #show" do

     before { get :show, params: { id: user.id } }
     it "assigns the requested user to @user" do
       assigns(:user).should eq user
     end
     it "renders  the :show template"
     it { expect(response).to have_http_status 200 }
   end

   describe "GET #new" do
     before { get :new }

     it "assigns a new User to @user" do
       assigns(:user).should be_a_new(User)
     end
     it "renders  the :new template"
   end
 end

【讨论】:

  • 非常感谢您的帮助!我已经在我的代码中替换了这部分,但 before { get :show, id: user.id} 会产生错误。是否可以向我展示如何重新安排第一个测试? #<:examplegroups::userscontroller::getshow> 的错误如下 NameError: undefined local variable or method user'
  • 感谢您的帮助!我认为我的代码中有一个基本错误。我已经像你一样更改了我的代码,现在我收到错误,方法 create 已定义 undefined method create
  • @Pyrmon55,将create 更改为FactoryGirl.create。为什么测试中有require 'factory_girl_rails' 行?如果你在 Gemfile 中有这个 gem,它应该会自动工作
  • 非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-03
  • 1970-01-01
  • 2012-01-18
  • 2021-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多