简体   繁体   中英

(Rails) Can't use variable made by FactoryBot in rspec

i have two model, post and comment post has many comment

this is my schema ->

  create_table 'posts', force: :cascade do |t|
    t.string 'title'
  end

  create_table 'comments', force: :cascade do |t|
    t.references :post, index: true, foreign_key: { on_delete: :cascade }
    t.string 'content'
  end

and my route is like ->

  resources :posts do
    resources :comments
  end

my post factory ->

FactoryBot.define do
  factory :post do
    sequence(:title) { |n| "title #{n}" }
  end
end

my comment factory ->

FactoryBot.define do
  factory :comment do
    sequence(:content) { |n| "content #{n}" }
    sequence(:post_id) { |n| n }
  end
end

so i tried to use these in request respec.

first i init the variable ()

-comments_spec.rb

  let(:new_post) { create(:post) }
  let(:comment) { create(:comment) }

then i use it

  describe '#edit' do
    it 'returns :edit view' do
      get edit_post_comment_path(new_post, comment)
      expect(response).to be_successful
    end
  end

but i get this error ->

     Failure/Error: let(:comment) { create(:comment) }
     
     ActiveRecord::InvalidForeignKey:
       PG::ForeignKeyViolation: ERROR:  insert or update on table "comments" violates foreign key constraint "fk_rails_2fd19c0db7"
       DETAIL:  Key (post_id)=(3) is not present in table "posts".

how can i change it to check access edit page? and why my result makes InvalidForeignKey error?

use association in comment factory to create a post and associate to comment

FactoryBot.define do
  factory :comment do
    sequence(:content) { |n| "content #{n}" }
    association :post
  end
end

Then you can pass created post as a param while creating new comment. If you do not pass the post as a param then it will create a new post using the factory defined for the post and associate it to a comment.

 let(:new_post) { create(:post) }
 let(:comment) { create(:comment, post: new_post) }
FactoryBot.define do
  factory :comment do
   sequence(:content) { |n| "content #{n}" }
   post_id { 1 }     #or post_id { Post&.first&.id }   
  end
end

U can use association in factory. Bonus: U can also use association model id in factory.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM