Notes on creating a many-to-many Factory with Rspec and testing it with SystemSpec [RSpec, FactoryBot]

background

I made a many-to-many relationship with Rspec and tested it with SystemSpec. Due to the complexity of the original table structure, I had a lot of trouble, so I will summarize the notes below.

The execution completion is as follows.

Table structure

The table structure looks like this. The main tables are ʻoffices (branch office of a company) and shops (stores that are business destinations), and ʻoffice (branch office) opens ʻevebt, and the stores shopsthat are business destinations there.Join. shops always has some category.

Image from Gyazo

The problem that was happening

Due to the model method, when I made factory of ʻevents, I neededshops` associated with it. However, due to the structure, if I wrote it like this, an error occurred.

let!(:shop){FactoryBot.create(:shop)}
let!(:event){FactoryBot.create(:event)}
#=>Here, the structure was such that an error would occur if there was no shop associated with the event.
let!(:event_shops){FactoryBot.create(:event_shop, event: event, shop: shop)}

Workaround

Therefore, I decided to create a factory that can define the related shop at the same time when the factory of ʻevent` is created.

Create a factory for events

The created Factory is as follows.

spec/factories/events.rb


FactoryBot.define do
  factory :event do
    office_id { nil }
    name { "Test event" }
    
    trait :with_shops do
      after(:create) do |event|
        category = FactoryBot.create(:category, :sequence)
        create_list(:shop, 1, events: [event], category: category)
      end
    end
  end
end

First, create a trait called with_shops in the factory of ʻevent so that you can also create the associated shop when you create ʻevent. Make it possible to create multiple shop factories with create_list (only one because only one is needed here), and [event] so that multiple instances of ʻevent can be entered from ʻevents. It is expressed as and an array.

In addition, I will explain later that category is purposely called using trait.

Make it callable in System Spec

spec/factories/categories.rb


FactoryBot.define do
  factory :category do
    name { "Medical system" }

    trait :sequence do
      sequence(:id, 100)
      name { "Clothing system" }
    end
  end
end

spec/system/events_spec.rb


let!(:event) { FactoryBot.create(:event, :with_shops, office: office, shops: [shop]) }
#You can't apply category to shop from here

Next, in the factory of category, ʻeventis generated multiple times in the view. Therefore, thecateogory of the shop generated at the same time must be set to a different ʻid (FK) each time, or an FK duplicate error will occur.

Also, when trying to apply category from system spec to shops of ʻevent, when trying to create a factory for shopinspec / factories / events.rb`," The foreign key does not exist "and I got an error.

Therefore, using sequence, I tried to create different categories of ʻid` (FK) one by one.

At the end (reference site, etc.)

It took a long time to resolve, but I'm glad I managed to resolve it! This time, the structure of the DB was complicated, so I had to write such a complicated Spec, but In the future, I would like to solidify the DB design so that simpler tests can be done. .. .. ..

▼ Articles that I especially referred to -Set up "many-to-many" and "multiple one-to-many" associations in Factory Girl -Use Factorybot traits to prepare data with complex associations with double has_many -FactoryBot (formerly FactoryGirl) sequence and .next

Recommended Posts

Notes on creating a many-to-many Factory with Rspec and testing it with SystemSpec [RSpec, FactoryBot]
(Ruby on Rails6) Creating a database and displaying it in a view
Run SystemSpec (RSpec) and Rubocop on CircleCI
Create a Java (Gradle) project with VS Code and develop it on a Docker container
Create a Java (Maven) project with VS Code and develop it on a Docker container
Build a bulletin board API with authentication authorization with Rails 6 # 3 RSpec, FactoryBot introduced and post model
Testing model with RSpec
[Docker] Build a site on Hugo and publish it on GitHub
Introduced Rspec and Factory Bot as a purchasing agency service