40
votes

How do I turn off transactional fixtures for only one spec (or Steak scenario) with RSpec 2? I tried some things found on the web without any success.

This leads to an undefined method exception.

describe "MyClass without transactional fixtures" do
  self.use_transactional_fixtures = false
  ...
end

This simply does nothing (transactional fixture is still on):

describe "MyClass without transactional fixtures" do
  RSpec.configure do |config|
    config.use_transactional_fixtures = false
  end
  ...
end

What else could I try?

6
it's really wired to want that. because you can't know what you have in your database.shingara
I hope that's not true for your code, too ;-) But seriously, for some testing scenarios you have to disable the transactional fixtures. For example, like in my case, to test Thinking Sphinx. Sphinx needs to update the search index from the "outside". And so it has to know the database content at a specific time.Zardoz
Just one thing to note; At least in my environment ( Rails4 rspec 2 ) if you for some reason include the rspec/rails_helper in any of your rspec files, it will cause any test after it in the suite or in subsequent files to be run transactionally again.Wedge Martin

6 Answers

9
votes

This used to be a bug (see ticket #197), but I seems to be okay now. I just don't know if it will work on a per test base (probably not). If you want to do this, you can disable transactional fixtures globally by putting config.use_transactional_fixtures = false on the spec_helper.rb and use DatabaseCleaner to set that.

I've had a similar problem when testing pages with javascript on the browser (a scenario that does not work with transactional fixtures). Here's how I managed to work around it: http://github.com/lailsonbm/contact_manager_app

34
votes

I usually add a helper like this:

def without_transactional_fixtures(&block)
  self.use_transactional_fixtures = false

  before(:all) do
    DatabaseCleaner.strategy = :truncation
  end

  yield

  after(:all) do
    DatabaseCleaner.strategy = :transaction
  end
end

Which lets me turn off transactional fixtures for a specific block in the specs:

describe "doing my thing" do
  without_transactional_fixtures do
    it "does something without transaction fixtures" do
      ...
    end
  end
end
9
votes

I've did it this way, with database_cleaner, in order to test code that uses transactions (which will conflict with transactional_fixtures or any other strategy to make transactional tests e.g. DatabaseCleaner.strategy = :truncation or :transaction):

# spec_helper.rb
config.use_transactional_fixtures = false
config.around(:each, :testing_transactions => true) do |ex|
    DatabaseCleaner.strategy = nil
    ex.run
    DatabaseCleaner.strategy = :truncation
end

and in my test cases:

it "should not save if one of objects are invalid", :testing_transactions => true
7
votes

I mixed both answers and it worked for me on RSpec 3:

config.around(:each, use_transactional_fixtures: false) do |example|
  self.use_transactional_fixtures = false
  example.run
  self.use_transactional_fixtures = true

  DatabaseCleaner.clean_with(:deletion)
end

You can then use it in the describe, context or it block

describe 'my test', use_transactional_fixtures: false do
   ...
end
4
votes

Not sure if that applies to RSpec2, but works fine with 3.

config.use_transactional_fixtures = true
config.around(:each, use_transactional_fixtures: false) do |example|
  self.use_transactional_tests = false
  example.run
  self.use_transactional_tests = true
end

Mind the use_transactional_fixtures (rspec-rails option) and use_transactional_tests (activerecord fixtures option) difference.

2
votes

Use use_transactional_tests instead of use_transactional_fixtures When Rspec 2.3.8 is being used

def without_transactional_fixtures(&block)
  self.use_transactional_tests = false

  before(:all) do
    DatabaseCleaner.strategy = :truncation
  end

  yield

  after(:all) do
    DatabaseCleaner.strategy = :transaction
  end

  self.use_transactional_tests = true
end