我的控制器中有一个庞大而复杂的#create方法。在创建模型实例的同时,我还将一个大文件保存到服务器上,对它进行了大量处理,还有一些其他的东西。
现在在我的其他测试中,我希望所有这些“副作用”都可用。所以在Factory Bot中仅仅创建一个模型实例是不够的,所以我需要从控制器运行整个#create
动作。我的问题是:
在工厂文件中运行控制器操作的语法是什么?似乎无法找到它。
对于这种事情,这是正常的做法吗?或者我应该避免依赖控制器的创建操作并在工厂中编写它的最小版本?
感谢。
答案 0 :(得分:2)
...在Factory Bot中,仅仅创建一个模型实例
是不够的
Factory Bot不是为了与控制器一起工作而构建的,因为它只关注对象。正如repo描述所述,它是一个用于将Ruby对象设置为测试数据的库。"
现在在我的其他测试中,我想要所有这些副作用'可用...我需要从控制器运行整个#create动作。
将Factory Bot视为仅用于模拟测试的模型数据。您的工厂不关心控制器和视图中的内容。
如果您想测试控制器操作,请查看controller specs或request specs。 (链接假设使用rspec。)
编写控制器或请求规范时,您可以使用工厂创建一个对象,然后在控制器/请求规范中使用该对象,从而测试您的创建操作对该对象的影响。
我的控制器中有一个庞大而复杂的#create方法。
我还建议如果它变得越来越长,就要打破你的创作动作。实现此目的的两种方法是controller concerns或service objects。这两种方法都可以使测试更容易,因为您可以单独测试每个关注/服务对象。
如果任务变得昂贵,您也可以考虑将任务移到后台(或客户端),因为这会阻碍请求并对性能产生负面影响。
直接回答您的问题:
在工厂文件中运行控制器操作的语法是什么?
没有一个,因为这不是Factory Bot的基础。
对于这种事情,这是正常的做法吗?
没有
或者我应该避免依赖控制器的创建操作并在工厂中编写它的最小版本?
不。但是如果控制器变得冗长而混乱,请随意打破关注点或服务对象之间的逻辑。
答案 1 :(得分:0)
所以在给出了一些想法之后,在@seancdavis的帮助下,我意识到FactoryBot不适合用于解雇'创造'行动。相反,我在before :each
块中运行它,因为这似乎是这样做的方式。
答案 2 :(得分:0)
还有另一种方法可以解决此问题,即利用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
也许有比这更优雅的解决方案,但是到目前为止,它已经可以很好地满足我的需求。