Fixtures in RSpec Fixtures in RSpec ruby-on-rails ruby-on-rails

Fixtures in RSpec


If you want to use fixtures with RSpec, specify your fixtures in the describe block, not within a before block:

describe StudentsController do  fixtures :students  before do    # more test setup  endend

Your student fixtures will get loaded into the students table and then rolled back at the end of each test using database transactions.


First of all: You cannot use method fixtures in :all / :context / :suite hook. Do not try to use fixtures in these hooks (like post(:my_post)).

You can prepare fixtures only in describe/context block as Infuse write earlier.

Call

fixtures :students, :teachers

do not load any data into DB! Just prepares helper methods students and teachers.Demanded records are loaded lazily in the moment when You first try to access them. Right before

dan=students(:dan) 

This will load students and teachers in delete all from table + insert fixtures way.

So if you prepare some students in before(:context) hook, they will be gone now!!

Insert of records is done just once in test suite.

Records from fixtures are not deleted at the end of test suite. They are deleted and re-inserted on next test suite run.

example:

 #students.yml   dan:     name: Dan    paul:     name: Paul #teachers.yml    snape:      name: Severusdescribe Student do  fixtures :students, :teachers    before(:context) do    @james=Student.create!(name: "James")  end  it "have name" do   expect(Student.find(@james.id)).to be_present   expect(Student.count).to eq 1   expect(Teacher.count).to eq 0     students(:dan)      expect(Student.find_by_name(@james.name)).to be_blank   expect(Student.count).to eq 2   expect(Teacher.count).to eq 1     endend#but when fixtures are in DB (after first call), all works as expected (by me)describe Teacher do  fixtures :teachers # was loaded in previous tests    before(:context) do    @james=Student.create!(name: "James")    @thomas=Teacher.create!(name: "Thomas")  end  it "have name" do   expect(Teacher.find(@thomas.id)).to be_present   expect(Student.count).to eq 3 # :dan, :paul, @james   expect(Teacher.count).to eq 2 # :snape, @thomas     students(:dan)         expect(Teacher.find_by_name(@thomas.name)).to be_present   expect(Student.count).to eq 3   expect(Teacher.count).to eq 2     endend

All expectations in tests above will pass

If these test are run again (in next suite) and in this order, than expectation

 expect(Student.count).to eq 1

will be NOT met! There will be 3 students (:dan, :paul and fresh new @james). All of them will be deleted before students(:dan) and only :paul and :dan will be inserted again.


before(:all) keeps the exact data around, as it's loaded/created once. You do your thing, and at the end of the test it stays. That's why bui's link has after(:all) to destroy or use before(:each); @var.reload!;end to get the latest data from the tests before. I can see using this approach in nested rspec describe blocks.