RSpec의 모델 단체 테스트에서 외래 키를 자동 추출하는 방법과 주의점 【초보자용】

개발 환경




시스템
버전


macOS Catalina
10.15.7

Ruby on Rails
6.0.0

pry_rails
4.0.0

번들러
2.1.4

rspec_rails

factory_bot_rails

faker



자동 추출이 왜 필요한가?



모델 단위 테스트에서는 어떻게 실제 데이터 보존 기능에 가까운 검증이 이루어지고 있는지가 열쇠가 되기 때문이다.

자식 모델의 인스턴스를 FactoryBot로 생성할 때, 부모 모델의 id를 외래 키로서 갖게 할 필요가 있어, 이것에는 몇개의 패턴인가하는 방법이 생각된다.

1. 임의의 숫자를 넣은 상태로 한다

spec/factories/address_order.rb
FactoryBot.define do
  factory :address_order do
# 省略
    item_id             { '1' }
    user_id             { '1' }
  end
end

2. Faker로 임의의 숫자를 생성

spec/factories/address_order.rb
FactoryBot.define do
  factory :address_order do
# 省略
    item_id             { Faker::Number.non_zero_digit }
    user_id             { Faker::Number.non_zero_digit }
  end
end

3. 상위 모델에서 연결되는 인스턴스의 ID를 추출합니다.

spec/factories/address_order.rb
FactoryBot.define do
  factory :address_order do
# 省略
# 外部キーのカラムは消してしまう
#   item_id
#   user_id
  end
end

spec/models/address_order_spec.rb
require 'rails_helper'

RSpec.describe AddressOrder, type: :model do
  before do
# 親モデルのインスタンスを生成する
    @user = FactoryBot.create(:user)
    @item = FactoryBot.create(:item)
# 親モデルのインスタンスからidを抽出する
    @order = FactoryBot.build(:address_order, user_id: @user.id, item_id: @item.id)
    sleep 0.1
  end
# 省略
end

어떠한 패턴이라도 문제없이 테스트를 실시할 수 있지만, 엄밀히 말하면 아이 모델의 인스턴스에 있어서의 외래 키는, 부모 모델의 묶고 있는 인스턴스로부터 병합되는 존재이기 때문에, 패턴 3으로 기술하는 것이 바람직하다.
이렇게하면 실제 데이터 저장 기능에 가까운 테스트를 수행 할 수 있습니다.

주의점



before 메소드내에 sleep 0.1 라고 하는 기술이 있지만, 이 1문이 없었던 경우 이하와 같은 에러에 조우했다.
(일부 생략) 이 오류 원인과 해결 방법에 관해서는 RSpec 테스트 중에 MySQL client is not connected을 참조했다.
한마디로, 인스턴스 생성에 과도한 부하가 걸려 버려서 발생하는 에러이다. 그 때문에, sleep 0.1 를 before 메소드내에 기술하는 것에 의해 인스턴스를 생성할 때마다 0.1초 처리를 대기시키는 것으로, 부하의 경감에 성공하고 있다.

결과



테스트가 완료되기까지 이전보다 조금 시간이 걸리게 되었지만, 보다 실제의 어제에 가까운 형태로 단위 테스트를 기술할 수 있었다.

참고 링크


  • RSpec 테스트 중에 MySQL client is not connected
  • 좋은 웹페이지 즐겨찾기