如何为已创建的工厂生成:attributes_?

问题描述 投票:0回答:2

更新(不要回答这个)

我刚刚得知这个问题实际上没有意义。这是基于我自己对工厂的误解以及它们是如何运作的。


整个想法是基于对FactoryBot如何工作的误解,特别是出于某种原因,我认为FactoryBot正在设置一些完全不同的宝石(Devise)实际负责的变量。

有没有简单的方法来访问已经建成的工厂的“虚拟属性”?

类似于:attributes_for,但是在Factory的实例而不是类上使用?

所以你可以这样做:

FactoryBot.define do
  factory :user do
    email { Faker::Internet.email }
    password { "password" }
    password_confirmation { "password" }
  end
end

@user = FactoryBot.build(:user)

@user.factory_attributes # Not a real method
#-> { email: "[email protected]", password: "123456", password_confirmation: "123456" }

为什么我想要这个

如果您想知道,我希望这能够缩短“登录”请求规范的以下代码。

由此:

let(:user_attributes) do
  FactoryBot.attributes_for(:user)
end

let(:user) do
  FactoryBot.create(:user, user_attributes)
end

# Triggers the create method in let(:user)
# Necessary to ensure the user exists in the database before testing sign in.
before { user } 

let(:user_params) do 
  { user: user_attributes }
end

it "redirects to the root path on successful sign in" do
  post user_session_path(params: user_params)
  expect(response).to redirect_to(root_path)
end

对此:

let(:user) do
  FactoryBot.create(:user)
end

let(:user_params) do 
  { user: user.factory_attributes }
end

it "redirects to the root path on successful sign in" do
  post user_session_path(params: user_params)
  expect(response).to redirect_to(root_path)
end

这比第一个更清洁,更少混淆,特别是对于较新的开发者(可能会看到有一点RSpec经验的人花费相当一段时间试图找出“{user}”之前的行中的内容

ruby factory-bot
2个回答
1
投票

有没有简单的方法来访问已经建成的工厂的“虚拟属性”?

我认为您对术语和/或工厂机器人如何工作感到困惑。你不建造工厂。工厂已经存在,它构建用户(在这种情况下)。

在构建/创建用户之后,它不知道工厂构建它。这是正确的。可以通过多种方式创建用户。如果该方法确实存在,那么当您使用User.create创建用户时,您希望它返回什么?


2
投票

FactoryBot.build(:user)返回ActiveRecord模型的实例。因此,您只需使用ActiveRecord::Base#attributes返回当前对象的属性列表:

@user = FactoryBot.build(:user)
@user.attributes

一旦工厂返回了User的实例,user就不再有关于它如何初始化的信息了。因此,无法读取实例上不存在的值。

解决方法可能是这样的:

let(:parameters) do
  { user: FactoryBot.attributes_for(:user) }
end

before do
  FactoryBot.create(:user, parameters[:user])
end

it "redirects to the root path on successful sign in" do
  post user_session_path(params: parameters)
  expect(response).to redirect_to(root_path)
end

但实际上,我认为你应该更清楚你真正关心的属性。您关心用户的电子邮件和用户密码 - 所有其他属性与此规范无关。因此我会像这样编写规范:

let(:email) { '[email protected]' }
let(:password) { 'secret' }

before do
  FactoryBot.create(:user, email: email, password: password, password_confirmation: password)
end

it "redirects to the root path on successful sign in" do
  post user_session_path(params: { user: { email: email, password: password } })
  expect(response).to redirect_to(root_path)
end
© www.soinside.com 2019 - 2024. All rights reserved.