Rspec / 在我的 rails 应用程序中创建新实例时,FactoryBot 工厂不是 运行 after_initialize
Rspec / FactoryBot factories are not running after_initialize when createing a new instance in my rails app
我有一些模型像这样使用 after_initialize
挂钩来设置大量默认属性和其他东西:
after_initialize do |some_model|
initializer(some_model)
end
def initializer(some_model)
#... loads of pre-processing
end
这一切 运行 在开发和生产中都很棒,但是在我的 FactoryBot 和 rspec 测试中,这个挂钩不是 运行ning。我有一个看起来像这样的工厂:
FactoryBot.define do
factory :some_model do
some_number { 1 }
is_it_something { false }
account { create(:user).accounts.first }
end
end
但我的测试看起来像这样:
some_model = create(:some_model)
some_model.initializer(some_model)
问题是我必须在创建 FactoryBot 模型后单独调用 initializer
。这导致了各种问题,因为 create()
触发了创建验证,但它们失败了,因为初始化程序不是 运行.
如何在创建新实例时让 FactoryBot 运行 after_initialize
?
谢谢。
(我这里可能用词有误,如有请指正。)
FactoryBot 为属性调用 setter,而不是构造函数,因此 build :some_model, some_attribute: 123, other_attribute: :foo
实际上等同于:
SomeModel.new.tap{|m|
m.some_attribute = 123
m.other_attribute = :foo
}
这种方法是在一个空对象上调用初始化程序,并且只有在这之后才会设置所有其他属性。
当您需要设置一些依赖于其他属性的属性时 - 我会选择像
这样的自定义设置器
def some_other_attribute=(val)
self.some_attribute = calculate(val)
super
end
或在 before_validation
中完成
您可以使用工厂的 after(:build)
回调来调用初始化程序,因为 factorybot 在初始化后设置属性。
FactoryBot.define do
factory :some_model do
some_number { 1 }
is_it_something { false }
account { create(:user).accounts.first }
after(:build) do |some_model|
some_model.initializer(some_model)
end
end
end
这样你就不必每次从工厂创建新对象时都调用它
总之,这个initializer
方法看起来有点代码味。我不确定它有什么作用,但也许有更好的方法可以防止这个问题。
我有一些模型像这样使用 after_initialize
挂钩来设置大量默认属性和其他东西:
after_initialize do |some_model|
initializer(some_model)
end
def initializer(some_model)
#... loads of pre-processing
end
这一切 运行 在开发和生产中都很棒,但是在我的 FactoryBot 和 rspec 测试中,这个挂钩不是 运行ning。我有一个看起来像这样的工厂:
FactoryBot.define do
factory :some_model do
some_number { 1 }
is_it_something { false }
account { create(:user).accounts.first }
end
end
但我的测试看起来像这样:
some_model = create(:some_model)
some_model.initializer(some_model)
问题是我必须在创建 FactoryBot 模型后单独调用 initializer
。这导致了各种问题,因为 create()
触发了创建验证,但它们失败了,因为初始化程序不是 运行.
如何在创建新实例时让 FactoryBot 运行 after_initialize
?
谢谢。
(我这里可能用词有误,如有请指正。)
FactoryBot 为属性调用 setter,而不是构造函数,因此 build :some_model, some_attribute: 123, other_attribute: :foo
实际上等同于:
SomeModel.new.tap{|m|
m.some_attribute = 123
m.other_attribute = :foo
}
这种方法是在一个空对象上调用初始化程序,并且只有在这之后才会设置所有其他属性。
当您需要设置一些依赖于其他属性的属性时 - 我会选择像
这样的自定义设置器def some_other_attribute=(val)
self.some_attribute = calculate(val)
super
end
或在 before_validation
您可以使用工厂的 after(:build)
回调来调用初始化程序,因为 factorybot 在初始化后设置属性。
FactoryBot.define do
factory :some_model do
some_number { 1 }
is_it_something { false }
account { create(:user).accounts.first }
after(:build) do |some_model|
some_model.initializer(some_model)
end
end
end
这样你就不必每次从工厂创建新对象时都调用它
总之,这个initializer
方法看起来有点代码味。我不确定它有什么作用,但也许有更好的方法可以防止这个问题。