|
| 1 | +--- |
| 2 | +chapter: Testing |
| 3 | +title: Factories |
| 4 | +--- |
| 5 | + |
| 6 | +When using ROM, you will need to test your code, and testing your code implies generating entities and use Factories to |
| 7 | +create records on your database. To do all of that, you can use `rom-factory`, which provides more or less same |
| 8 | +functionnalities as `FactoryBot`. |
| 9 | + |
| 10 | +### Install RomFactory |
| 11 | + |
| 12 | +In your gemfile: |
| 13 | + |
| 14 | +```ruby |
| 15 | +gem 'rom-factory' |
| 16 | +``` |
| 17 | + |
| 18 | +### Setup ROMFactory |
| 19 | + |
| 20 | +Then on your spec root file (like `spec_helper`), you have to initialize your factory: |
| 21 | + |
| 22 | +```ruby |
| 23 | +# Build database configuration |
| 24 | +db_config = { |
| 25 | + adapter: 'mysql2', |
| 26 | + database: 'db_name', |
| 27 | + host: 'database.host.io', |
| 28 | + username: 'username', |
| 29 | + password: 'password', |
| 30 | + port: 3306 |
| 31 | +} |
| 32 | + |
| 33 | +# Init your ROM container |
| 34 | +rom = ROM.container(:sql, db_config)do |config| |
| 35 | + # Register ROM related files, especially Relations |
| 36 | + config.auto_registration('../app/') # if your sources are in app folder |
| 37 | + end |
| 38 | + |
| 39 | +# Declare your factory |
| 40 | +YourFactory = ROM::Factory.configure do |config| |
| 41 | + config.rom = rom |
| 42 | +end |
| 43 | + |
| 44 | +# Load your factories' files |
| 45 | +Dir[App.root + '/spec/factories/**/*.rb'].each { |f| require f } # if you plan to put your factory files `spec/factories` |
| 46 | +``` |
| 47 | + |
| 48 | +### Define your factory |
| 49 | + |
| 50 | +Then you can define your factories: |
| 51 | + |
| 52 | +```ruby |
| 53 | +YourFactory.define(:user) do |f| |
| 54 | + f.sequence(:name) { |n| "User#{n}" } |
| 55 | + f.website 'http://personal.website' |
| 56 | + f.some_integer 42 |
| 57 | + f.created_at Time.now.utc |
| 58 | +end |
| 59 | +``` |
| 60 | + |
| 61 | +You can define multiple builders on the same factory. |
| 62 | +In this example, the relation `users` (ie builder name pluralized) must exist in your ROM::RelationRegistry`. |
| 63 | + |
| 64 | +### Use your factory |
| 65 | + |
| 66 | +In your tests, you can either get an instance from your factory only in memory, or in memory but that has been |
| 67 | +persisted on your database. |
| 68 | + |
| 69 | +Let's suppose that `UserRepo` is your Users' repository and it has a relation to `users` SQL table. |
| 70 | + |
| 71 | +```ruby |
| 72 | +user1 = YourFactory[:user] |
| 73 | +p user1 |
| 74 | +#=> #<ROM::Struct::User id=84 name="User1" website="http://personnal.website" some_integer=42 created_at=2019-04-02 08:50:34 +0000> |
| 75 | + |
| 76 | +p UserRepo.users.by_pk(user1.id).one |
| 77 | +#=> #<ROM::Struct::User id=84 name="User1" website="http://personnal.website" some_integer=42 created_at=2019-04-02 08:50:34 +0000> |
| 78 | + |
| 79 | +user2 = YourFactory.structs[:user] |
| 80 | +p user2 |
| 81 | +#=> #<ROM::Struct::User id=85 name="User2" website="http://personnal.website" some_integer=42 created_at=2019-04-02 08:50:46 +0000> |
| 82 | + |
| 83 | +p UserRepo.users.by_pk(user2.id).one |
| 84 | +#=> nil |
| 85 | + |
| 86 | +user3 = YourFactory.structs[:user, name: "toto", website: nil] |
| 87 | +p user3 |
| 88 | +#=> #<ROM::Struct::User id=85 name="toto" website=nil some_integer=42 created_at=2019-04-02 08:51:20 +0000> |
| 89 | +``` |
| 90 | + |
| 91 | +### Going further |
| 92 | + |
| 93 | +#### Associations |
| 94 | + |
| 95 | +RomFactory supports associations that you declared in your Relations. |
| 96 | +```ruby |
| 97 | +YourFactory.define(:user) do |f| |
| 98 | + # this will use :team builder to create a team for a user |
| 99 | + f.association(:team) |
| 100 | + |
| 101 | + # this will create 2 posts for a user using :post builder |
| 102 | + f.association(:posts, count: 2) |
| 103 | +end |
| 104 | +``` |
| 105 | + |
| 106 | +#### Faker |
| 107 | + |
| 108 | +ROMFactory comes with Faker gem: |
| 109 | + |
| 110 | +```ruby |
| 111 | +YourFactory.define(:foo) do |f| |
| 112 | + f.bar { fake(:number, :between, 10, 100) } |
| 113 | +end |
| 114 | +``` |
| 115 | + |
| 116 | +#### Traits |
| 117 | + |
| 118 | +ROMFactory supports traits: |
| 119 | + |
| 120 | +```ruby |
| 121 | +YourFactory.define(:user) do |f| |
| 122 | + f.registered true |
| 123 | + |
| 124 | + f.trait :not_registered do |t| |
| 125 | + t.registered false |
| 126 | + end |
| 127 | +end |
| 128 | + |
| 129 | +p YourFactory[:user, :not_registered] |
| 130 | +#=> #<ROM::Struct::User id=130 registered=false> |
| 131 | +``` |
| 132 | + |
| 133 | +### Inheritance |
| 134 | +You can extend existing builders, see [Rom Factory annoncement](https://rom-rb.org/blog/announcing-rom-factory/) for an |
| 135 | +example. |
| 136 | + |
| 137 | + |
| 138 | +### Read more: |
| 139 | +* [Rom Factory annoncement](https://rom-rb.org/blog/announcing-rom-factory/) |
| 140 | +* [Rom Factory repository](https://github.com/rom-rb/rom-factory/) |
0 commit comments