Rails 5 - RSpec 与 FactoryGirl 给出错误参数数量错误
Rails 5 - RSpec with FactoryGirl giving error wrong number of arguments
这是我第一次在使用 RSpec 和 FactoryGirl
的 rails 项目上编写测试用例
当我 运行 测试用例时,出现以下错误
wrong number of arguments (given 0, expected 1)
我浏览了 stack over flow 上的其他帖子,它们对我的情况没有太大帮助。
我试过的
我正在一个名为 ImportFeed
的模型上编写测试用例,它看起来如下所示
class ImportFeed < ApplicationRecord
belongs_to :staffroom
belongs_to :user, optional: true # We don't have to have a user
validates_presence_of :url, :feed_type
validates :enabled, presence: true, allow_blank: true
def initialize(params)
super(params)
self.enabled = false if self.enabled.blank?
self.default_radius = DEFAULT_RADIUS if self.default_radius.blank?
self.default_days = DAYS_DEFAULT if self.default_days.blank?
end
end
这是我的测试用例的样子
require 'rails_helper'
describe JobImporters::JoraJobImporter, '.run' do
it 'should create an instance of ImportFeed' do
feed = ImportFeed::new FactoryGirl.create(:import_feed, :import1)
expect(feed).to be_a ImportFeed
end
end
这是工厂
FactoryGirl.define do
factory :import_feed do
trait :import1 do
enabled true
feed_type 'example'
staffroom_id 7526
url Faker::Internet::url
end
end
end
当我 运行 这个问题时,我得到了这个问题开头提到的错误,
如果我在没有 FactoryGirl 的情况下将数据传递给测试用例,那么我的测试用例可以工作并通过,例如,如果我替换
feed = ImportFeed::new FactoryGirl.create(:import_feed, :import1)
和
feed = ImportFeed::new enabled: true, staffroom_id: 7526, feed_type: 'example', url: Faker::Internet::url
测试用例通过。
如果有人能指出我这里做错了什么,我将不胜感激。
我认为您只是使用 initialize
方法根据条件更改值:
def initialize(params)
super(params)
self.enabled = false if self.enabled.blank?
self.default_radius = DEFAULT_RADIUS if self.default_radius.blank?
self.default_days = DAYS_DEFAULT if self.default_days.blank?
end
你不应该覆盖它(我的建议),因为它可能会破坏很多东西。因此,您可以像这样更改回调值(before_validation, before_save, before_create, after_initialize
适合您的值):
before_create :set_default_radius, if: proc { |feed| feed.default_radius.blank? }
def set_default_radius
self.default_radius = DEFAULT_RADIUS
end
最好的方法是在数据库中设置默认值。您可以在迁移中定义它:
def up
change_column :import_feeds, :default_radius, :integer, default: 0
end
def down
change_column :import_feeds, :default_radius, :integer, default: nil
end
因此,如果未定义该值,它将始终设置为迁移文件中提到的默认值。
你也可能读过几个与此相关的问题,其中有一些很好的答案和解释:
How to override "new" method for a rails model
Why is overriding ActiveRecord::Base.initialize wrong?
因为你重写了initialize
方法,所以你得到了意外的异常。
Don't override initialize on ActiveRecord objects
ActiveRecord::Base doesn't always use new to create objects, so initialize might not be called. [link]
为了解决您的问题,您应该在回调中设置您的属性
class ImportFeed < ApplicationRecord
# ...
after_initialize :set_my_attributes
private
def set_my_attributes
self.enabled = false if self.enabled.blank?
self.default_radius = DEFAULT_RADIUS if self.default_radius.blank?
self.default_days = DAYS_DEFAULT if self.default_days.blank?
end
end
还有一件事:
您正在测试创建 ImportFeed
功能的实例,因此您应该将参数传递给 new
或 create
方法来测试它,但是您传递了 ImportFeed
到它(来自 FactoryGirl
)。
根据文档,ActiveRecord#new
仅接受 Hash(如果您不传递任何内容,则默认参数为 {}
)。
如果您将对象传递给它,您将获得 ArgumentError
异常以及 "When assigning attributes, you must pass a hash as an argument" 消息
def assign_attributes(new_attributes)
if !new_attributes.respond_to?(:stringify_keys)
raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
end
return if new_attributes.empty?
attributes = new_attributes.stringify_keys
_assign_attributes(sanitize_for_mass_assignment(attributes))
end
这是我第一次在使用 RSpec 和 FactoryGirl
的 rails 项目上编写测试用例当我 运行 测试用例时,出现以下错误
wrong number of arguments (given 0, expected 1)
我浏览了 stack over flow 上的其他帖子,它们对我的情况没有太大帮助。
我试过的
我正在一个名为 ImportFeed
的模型上编写测试用例,它看起来如下所示
class ImportFeed < ApplicationRecord
belongs_to :staffroom
belongs_to :user, optional: true # We don't have to have a user
validates_presence_of :url, :feed_type
validates :enabled, presence: true, allow_blank: true
def initialize(params)
super(params)
self.enabled = false if self.enabled.blank?
self.default_radius = DEFAULT_RADIUS if self.default_radius.blank?
self.default_days = DAYS_DEFAULT if self.default_days.blank?
end
end
这是我的测试用例的样子
require 'rails_helper'
describe JobImporters::JoraJobImporter, '.run' do
it 'should create an instance of ImportFeed' do
feed = ImportFeed::new FactoryGirl.create(:import_feed, :import1)
expect(feed).to be_a ImportFeed
end
end
这是工厂
FactoryGirl.define do
factory :import_feed do
trait :import1 do
enabled true
feed_type 'example'
staffroom_id 7526
url Faker::Internet::url
end
end
end
当我 运行 这个问题时,我得到了这个问题开头提到的错误,
如果我在没有 FactoryGirl 的情况下将数据传递给测试用例,那么我的测试用例可以工作并通过,例如,如果我替换
feed = ImportFeed::new FactoryGirl.create(:import_feed, :import1)
和
feed = ImportFeed::new enabled: true, staffroom_id: 7526, feed_type: 'example', url: Faker::Internet::url
测试用例通过。
如果有人能指出我这里做错了什么,我将不胜感激。
我认为您只是使用 initialize
方法根据条件更改值:
def initialize(params)
super(params)
self.enabled = false if self.enabled.blank?
self.default_radius = DEFAULT_RADIUS if self.default_radius.blank?
self.default_days = DAYS_DEFAULT if self.default_days.blank?
end
你不应该覆盖它(我的建议),因为它可能会破坏很多东西。因此,您可以像这样更改回调值(before_validation, before_save, before_create, after_initialize
适合您的值):
before_create :set_default_radius, if: proc { |feed| feed.default_radius.blank? }
def set_default_radius
self.default_radius = DEFAULT_RADIUS
end
最好的方法是在数据库中设置默认值。您可以在迁移中定义它:
def up
change_column :import_feeds, :default_radius, :integer, default: 0
end
def down
change_column :import_feeds, :default_radius, :integer, default: nil
end
因此,如果未定义该值,它将始终设置为迁移文件中提到的默认值。
你也可能读过几个与此相关的问题,其中有一些很好的答案和解释:
How to override "new" method for a rails model
Why is overriding ActiveRecord::Base.initialize wrong?
因为你重写了initialize
方法,所以你得到了意外的异常。
Don't override initialize on ActiveRecord objects ActiveRecord::Base doesn't always use new to create objects, so initialize might not be called. [link]
为了解决您的问题,您应该在回调中设置您的属性
class ImportFeed < ApplicationRecord
# ...
after_initialize :set_my_attributes
private
def set_my_attributes
self.enabled = false if self.enabled.blank?
self.default_radius = DEFAULT_RADIUS if self.default_radius.blank?
self.default_days = DAYS_DEFAULT if self.default_days.blank?
end
end
还有一件事:
您正在测试创建 ImportFeed
功能的实例,因此您应该将参数传递给 new
或 create
方法来测试它,但是您传递了 ImportFeed
到它(来自 FactoryGirl
)。
根据文档,ActiveRecord#new
仅接受 Hash(如果您不传递任何内容,则默认参数为 {}
)。
如果您将对象传递给它,您将获得 ArgumentError
异常以及 "When assigning attributes, you must pass a hash as an argument" 消息
def assign_attributes(new_attributes)
if !new_attributes.respond_to?(:stringify_keys)
raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
end
return if new_attributes.empty?
attributes = new_attributes.stringify_keys
_assign_attributes(sanitize_for_mass_assignment(attributes))
end