FactoryBotでORMに依存しないClassを生成できるようにする
🧑🏻‍💻

FactoryBotでORMに依存しないClassを生成できるようにする

Category
Author
Tags
Description
Railsといえばrspecですが、テストデータの作成によくFactoryBotが使われます。FactoryBotはActiveRecordに依存していて大体ただのクラスを生成するというよりも、データベースに紐付いたモデルが生成されます。今回はActiveRecordに紐付いていなくてもObjectが生成できるよっていう記事になります。
Published
October 22, 2022
Last Updated
Last Updated October 28, 2022
Writings
この記事は約4分で読めます

💡この記事でわかること・解決すること

Railsといえばrspecですが、テストデータの作成によくFactoryBotが使われます。FactoryBotはActiveRecordに依存していて大体ただのクラスを生成するというよりも、データベースに紐付いたモデルが生成されます。今回はActiveRecordに紐付いていなくてもObjectが生成できるよっていう記事になります。

✌️やったこと

例えばこんなORMに依存していないUserクラスがあった場合に、 FactoryBot.build でクラスをnewしてくれます。
class User attr_accessor :name end FactoryBot.define do factory :user do name "Amy" end end user = FactoryBot.build(:user)
 
👉
ちなみに FactoryBot.create(:user) するとこのモデルはActiveRecordに紐付いていないのでNoMethodErrorで死ぬので注意
 
ただ大抵は constructor メソッドである initialize があると思うのでこのままだとinitialize時に NoMethodErrorで死んでしまいます。
そんなときは initialize_with でnewをOverrideしてあげましょう。これで生成できるようになります。
class User attr_reader :name def initialize(data = {}) @name = data[:name] end end FactoryBot.define do factory :user do name "Amy" initialize_with { new(attributes) } end end
では、これほどシンプルではなく initializeにロジックが含まれていた場合はどうでしょうか?
initialize_with はOverrideしてるだけなのでFactoryBotに項目に合うデータを突っ込んであげればとりあえず生成はできます。
class User attr_reader :name def initialize(data = {}) @name = data[:response][:name] end end FactoryBot.define do factory :user do initialize_with { name = 'Amy' data = { "response": { "name": name } } new(name) } end end
 
利用用途としては外部APIのResponseが特定の型を書いておいてAPI ClientをMockし、より中間のServiceクラスをMockせずにrspecを書くことができます。

🏌️‍♂️おわりに

Serviceクラス自体にも当然テストコードはあると思いますが、中がブラックボックスになりがちなのでController側である程度制御してあげるとより変更してもテストで落ちてくれる強いコードが書けると思います。
 
え?外部APIのResponseが変わって本番障害が起きた???それは知らない 😇

参考

 
いかがでしたか?この記事が良いと思ったらシェアお願いします!著者がすごく喜びます。