yaru
yaru

Reputation: 1310

Why model contains old data in DB after reload?

Should not before(:all) be executed only once? In my example the bottom test fails, because db record contains old data (name == "John"). Why so? I changed it in test above it to "Irow".

describe "Widget" do
before(:all) do
  @widget = Widget.create(name: "John")
end

it "changes Widget's #name in DB" do
  expect do
    @widget.name = "Irow"
    @widget.save!
  end.to change { @widget.reload.name}.from("John").to("Irow")
end

it "#name must be updated in DB by previous test" do
  expect(@widget.reload.name).to eq("Irow") # failing test
end

end

Upvotes: 1

Views: 101

Answers (1)

Marcin Kołodziej
Marcin Kołodziej

Reputation: 5313

This answer assumes that either in your rails_helper.rb or spec_helper.rb there is a line config.use_transactional_fixtures = true.

What your tests are doing is running each test in a dedicated transaction and rolling back said transaction after the test is finished.

Your first test will change the @widget name to Irow, pass successfully and rollback the changes to the database.

This puts you in a state where after this test

@widget.name == "Irow"

but

@widget.reload.name == "John"

as the transaction which changed the name to Irow was rolled back, so the row in database has John again.

The other thing worth mentioning is that you might be running your tests in a random order (config.order = :random), thus your tests would be blinking if you were not running each test in a dedicated transaction.

Try to make your tests as isolated as possible, use before(:all) only if it really makes sense (perhaps for some really expensive operations).

Upvotes: 1

Related Questions