这是我第一次在使用RSpec和FactoryGirl的rails项目上编写测试用例
当我运行测试用例时,我收到以下错误
错误的参数数量(给定0,预期为1)
我已经浏览过堆栈上的其他帖子,但在我的情况下它们没什么用处。
我尝试了什么
我正在一个名为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
测试用例通过。
如果有人能指出我在这里做错了什么,我将非常感激。
答案 0 :(得分:2)
因为你覆盖了initialize
方法,所以你得到了意想不到的异常。
不要覆盖ActiveRecord对象的初始化 ActiveRecord :: Base并不总是使用new来创建对象,因此可能不会调用initialize。 [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
功能的实例,因此您应该将params传递给new
或create
方法来测试它,但是您传递的是{{1 (来自ImportFeed
)。
根据文档,FactoryGirl
仅接受Hash(如果您没有传递任何内容,则默认参数为ActiveRecord#new
。)
如果您将对象传递给它,您将获得{}
异常以及“在分配属性时,您必须将散列作为参数传递”消息
ArgumentError
答案 1 :(得分:1)
我认为您只是使用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