在 Factory Bot 中使用控制器创建动作
Using controller create action in Factory Bot
我的控制器中有一个庞大而复杂的#create 方法。在创建模型实例时,我还将一个大文件保存到服务器,对其进行一系列处理,以及其他一些事情。
现在在我的其他测试中,我希望所有这些 'side effects' 都可用。所以在 Factory Bot 中,仅仅创建一个模型实例是不够的,所以我需要 运行 来自控制器的整个 #create
动作。我的问题是:
运行在工厂文件中设置控制器动作的语法是什么?好像找不到。
这是对这类事情的正常做法吗?或者我应该避免依赖控制器的创建操作并在工厂中编写它的最小版本吗?
谢谢。
... in Factory Bot it's not sufficient to simply create a model instance
Factory Bot 不是为与控制器一起工作而构建的,因为它只专注于对象。正如回购描述所述,它是 "A library for setting up Ruby objects as test data."
Now in my other tests I want all those 'side effects' to be available ... I need to run the whole #create action from the controller.
将 Factory Bot 视为仅用于模拟模型数据以进行测试的地方。你的工厂不关心你在你的控制器和视图中有什么。
如果你想测试控制器的动作,你应该看看controller specs or request specs。 (链接假定使用 rspec。)
在编写控制器或请求规范时,您可以使用您的工厂创建一个对象,然后您可以在您的 controller/request 规范中使用该对象,从而测试您的创建操作对该对象的影响。
I have a large and complicated #create method in my controller.
如果创建操作越来越长,我还建议将其拆分。 controller concerns or service objects 有两种实现方法。这两种方法也会使测试更容易,因为您可以单独测试每个 concern/service 对象。
如果任务变得昂贵,您也可以考虑将任务移至后台(或客户端),因为这会阻碍请求并对性能产生负面影响。
直接回答您的问题:
What is the syntax for running the controller action in the factory file?
没有,因为这不是 Factory Bot 的目标。
Is that a normal practice for this sort of thing?
没有
Or should I avoid depending on controller's create action and write a minimal version of it in the factory?
没有。但是,如果控制器变得又长又乱,请随意分解关注点或服务对象之间的逻辑。
所以在考虑了一下并在@seancdavis 的帮助下,我意识到 FactoryBot 不适合触发 'create' 动作。相反,我 运行 它在 before :each
块中,因为这似乎是实现它的方法。
还有另一种方法可以解决这个问题,那就是利用 FactoryBot 的回调。在我的 users#create 操作中,我自动将用户添加到特定组织,因此我通过向用户工厂添加 after(:create)
块来复制种子数据的这种行为。我还发现我可以通过将 after(:create)
块放在这样的特征中来防止我的测试套件的其余部分变慢:
FactoryBot.define do
factory :user do
first_name { Faker::Name.unique.first_name }
trait :with_organization do
after(:create) do |user|
org = Organization.find_by(name: 'Doctors Without Borders')
FactoryBot.create(:organization_user, organization: org, user: user)
end
end
end
end
也许还有比这更优雅的解决方案,但到目前为止它对我的需求来说效果很好。
我的控制器中有一个庞大而复杂的#create 方法。在创建模型实例时,我还将一个大文件保存到服务器,对其进行一系列处理,以及其他一些事情。
现在在我的其他测试中,我希望所有这些 'side effects' 都可用。所以在 Factory Bot 中,仅仅创建一个模型实例是不够的,所以我需要 运行 来自控制器的整个 #create
动作。我的问题是:
运行在工厂文件中设置控制器动作的语法是什么?好像找不到。
这是对这类事情的正常做法吗?或者我应该避免依赖控制器的创建操作并在工厂中编写它的最小版本吗?
谢谢。
... in Factory Bot it's not sufficient to simply create a model instance
Factory Bot 不是为与控制器一起工作而构建的,因为它只专注于对象。正如回购描述所述,它是 "A library for setting up Ruby objects as test data."
Now in my other tests I want all those 'side effects' to be available ... I need to run the whole #create action from the controller.
将 Factory Bot 视为仅用于模拟模型数据以进行测试的地方。你的工厂不关心你在你的控制器和视图中有什么。
如果你想测试控制器的动作,你应该看看controller specs or request specs。 (链接假定使用 rspec。)
在编写控制器或请求规范时,您可以使用您的工厂创建一个对象,然后您可以在您的 controller/request 规范中使用该对象,从而测试您的创建操作对该对象的影响。
I have a large and complicated #create method in my controller.
如果创建操作越来越长,我还建议将其拆分。 controller concerns or service objects 有两种实现方法。这两种方法也会使测试更容易,因为您可以单独测试每个 concern/service 对象。
如果任务变得昂贵,您也可以考虑将任务移至后台(或客户端),因为这会阻碍请求并对性能产生负面影响。
直接回答您的问题:
What is the syntax for running the controller action in the factory file?
没有,因为这不是 Factory Bot 的目标。
Is that a normal practice for this sort of thing?
没有
Or should I avoid depending on controller's create action and write a minimal version of it in the factory?
没有。但是,如果控制器变得又长又乱,请随意分解关注点或服务对象之间的逻辑。
所以在考虑了一下并在@seancdavis 的帮助下,我意识到 FactoryBot 不适合触发 'create' 动作。相反,我 运行 它在 before :each
块中,因为这似乎是实现它的方法。
还有另一种方法可以解决这个问题,那就是利用 FactoryBot 的回调。在我的 users#create 操作中,我自动将用户添加到特定组织,因此我通过向用户工厂添加 after(:create)
块来复制种子数据的这种行为。我还发现我可以通过将 after(:create)
块放在这样的特征中来防止我的测试套件的其余部分变慢:
FactoryBot.define do
factory :user do
first_name { Faker::Name.unique.first_name }
trait :with_organization do
after(:create) do |user|
org = Organization.find_by(name: 'Doctors Without Borders')
FactoryBot.create(:organization_user, organization: org, user: user)
end
end
end
end
也许还有比这更优雅的解决方案,但到目前为止它对我的需求来说效果很好。