[英]Rails testing using Rspec and FactoryBot
I am new to rails rspec testing, I currently need to created nested data structure and using factorybot for data.我是 rails rspec 测试的新手,我目前需要创建嵌套数据结构并使用 factorybot 数据。 And while it works for controller testing.
虽然它适用于控制器测试。 Its not letting me do simple Factorybot.create(:model).
它不允许我做简单的 Factorybot.create(:model)。 I have searched a lot.
我已经搜索了很多。 But didn't seem to find or understand a solution.
但似乎没有找到或理解解决方案。 So, data structure i need to create is something like:
所以,我需要创建的数据结构是这样的:
"email":"",
"name":"",
"personalDetail":{
"height":"",
"weight":"",
"color":""
}
"address":{
"street":"",
"postal_code":""
},
"experience":""
}
(**note. this not association related, data in controller is received in such a way. There is no relationship involved) while i am currently achieving this structure using (**注意。这与关联无关,控制器中的数据以这种方式接收。不涉及任何关系)而我目前正在使用
initialize_with{{
"email":"",
"name":"",
"personalDetail":{
"height":"",
"weight":"",
"color":""
}
"address":{
"street":"",
"postal_code":""
},
"experience":""
}}
its works for controller testing but it i'm not able to change key value while testing like:它适用于控制器测试,但我无法在测试时更改键值,例如:
FactoryBot.create(:model, name:"xyz")
, and also is not working for FactoryBot.create(:model), which is giving me error of ,并且也不适用于 FactoryBot.create(:model),这给了我错误
** Api::V1::someController get #index Failure/Error: FactoryBot.create(:model) ** Api::V1::someController get #index 失败/错误:FactoryBot.create(:model)
NoMethodError:
undefined method `save!' for #<Hash:0x0000563db7324060>
# ./spec/controllers/api/v1/somecontroller_spec.rb:11:in `block (2 levels) in <main>'
# -e:1:in `<main>' **
So, my question is how can i generate this structure using FactoryBot usual method.所以,我的问题是如何使用 FactoryBot 通常的方法生成这个结构。 ie
IE
factory :job_application do
field1 { "" }
field2 { "" }
end
so that i can use it usual way.这样我就可以正常使用它了。
factory :job_application
will guess that you want to make an object of the class JobApplication
. factory :job_application
会猜测您想要创建JobApplication
类的对象。 To make a Hash
you need to make it explicit.要制作
Hash
您需要使其明确。 See Defining Factories .请参阅定义工厂。
factory :job_application, class: Hash
Because Hash.new
does not take a bunch of key/value pairs, you need to override the default initialization behavior.因为
Hash.new
不需要一堆键/值对,所以你需要覆盖默认的初始化行为。 I've found the simplest thing to do is to return the attributes
of the factory.我发现最简单的方法是返回工厂的
attributes
。 See Custom Construction .请参阅自定义构造。
Those use symbol keys, you want string keys, so we use deep_stringify_keys
.那些使用符号键,你需要字符串键,所以我们使用
deep_stringify_keys
。 This also takes care of cloning attributes
just in case.以防万一,这也会处理克隆
attributes
。
factory :job_application, class: Hash do
initialize_with do
attributes.deep_stringify_keys
end
end
Now you can add attributes in the normal way.现在您可以以正常方式添加属性。
factory :job_application, class: Hash do
email { "jorb@coachz.biz" }
initialize_with do
attributes.deep_stringify_keys
end
end
Because there is no save
method, you can only build
these Hash factories.因为没有
save
方法,所以只能build
这些Hash工厂。
# Yes
jorb = FactoryBot.build(:job_application)
# No
jorb = FactoryBot.create(:job_application)
I find myself doing this a lot, so I've built a string_hash
factory to inherit from.我发现自己
string_hash
这样做,所以我建立了一个string_hash
工厂来继承。
factory :string_hash, class: Hash do
initialize_with do
attributes.deep_stringify_keys
end
end
factory :job_application, parent: :string_hash do
email { "jorb@coachz.biz" }
end
If you want nested hashes, I suggest you make additional factories and associate them together.如果您想要嵌套哈希,我建议您制作额外的工厂并将它们关联在一起。 This allows you to easily change the values in the nested hashes.
这使您可以轻松更改嵌套散列中的值。
Associations default to using create
, we need to explicitly build
our associations.关联默认使用
create
,我们需要明确地build
我们的关联。 See Associations .请参阅关联。
factory :address, parent: :string_hash do
street { "Ahead St." }
postal_code { "12345" }
end
factory :job_application, parent: :string_hash do
association :address, strategy: :build
email { "jorb@coachz.biz" }
name { "Coach Z" }
end
build(:job_application,
address: build(:address, street: "Sesame St.")
)
Do ask yourself whether it makes sense to define these as models .一定要问问自己将这些定义为模型是否有意义。 This makes them work with normal factories and features like validation and you can add methods and all that good stuff.
这使它们可以与普通工厂和验证等功能一起使用,并且您可以添加方法和所有好东西。
Since this is data you receive in a controller it might benefit from having validations and methods.由于这是您在控制器中收到的数据,因此它可能会受益于验证和方法。 See ActiveModel Form Objects by ThoughtBot .
请参阅ThoughtBot 的 ActiveModel 表单对象。
class JobApplication
include ActiveModel::Model
include ActiveModel::Validations
attr_accessor :email, :name, :address
validates :name, :email, presence: true
end
class Address
include ActiveModel::Model
attr_accessor :street, :postal_code
end
factory :address do
street { "Ahead St." }
postal_code { "12345" }
end
factory :job_application do
# Can't save a Model either.
association :address, strategy: :build
email { "jorb@coachz.biz" }
name { "Coach Z" }
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.