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

时间:2018-09-11 16:38:50

标签: ruby factory-bot

更新(不回答)

我刚刚了解到这个问题实际上没有任何意义。这是基于我对工厂的误解以及工厂的运作方式。


整个想法是基于对FactoryBot的工作原理的误解,特别是由于某些原因,我认为FactoryBot设置了一些变量,而这些变量实际上是由完全不同的gem(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: "name@gmail.com", 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经验很少的人花了很多时间试图弄清楚“在{用户}之前”这一行到底在做什么)

2 个答案:

答案 0 :(得分: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) { 'foobar@example.tld' }
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

答案 1 :(得分:1)

  

是否有任何简便的方法来访问已建工厂的“虚拟属性”?

我认为您对术语和/或工厂漫游器的工作方式感到困惑。您没有建立工厂。工厂已经存在,并且可以建立用户(在这种情况下)。

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