1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
# Transactions
When you run `rails generate rspec:install`, the `spec/rails_helper.rb` file
includes the following configuration:
```ruby
RSpec.configure do |config|
config.use_transactional_fixtures = true
end
```
The name of this setting is a bit misleading. What it really means in Rails
is "run every test method within a transaction." In the context of rspec-rails,
it means "run every example within a transaction."
The idea is to start each example with a clean database, create whatever data
is necessary for that example, and then remove that data by simply rolling back
the transaction at the end of the example.
### Disabling transactions
If you prefer to manage the data yourself, or using another tool like
[database_cleaner](https://github.com/bmabey/database_cleaner) to do it for you,
simply tell RSpec to tell Rails not to manage transactions:
```ruby
RSpec.configure do |config|
config.use_transactional_fixtures = false
end
```
### Data created in `before(:example)` are rolled back
Any data you create in a `before(:example)` hook will be rolled back at the end of
the example. This is a good thing because it means that each example is
isolated from state that would otherwise be left around by the examples that
already ran. For example:
```ruby
describe Widget do
before(:example) do
@widget = Widget.create
end
it "does something" do
expect(@widget).to do_something
end
it "does something else" do
expect(@widget).to do_something_else
end
end
```
The `@widget` is recreated in each of the two examples above, so each example
has a different object, _and_ the underlying data is rolled back so the data
backing the `@widget` in each example is new.
### Data created in `before(:context)` are _not_ rolled back
`before(:context)` hooks are invoked before the transaction is opened. You can use
this to speed things up by creating data once before any example in a group is
run, however, this introduces a number of complications and you should only do
this if you have a firm grasp of the implications. Here are a couple of
guidelines:
1. Be sure to clean up any data in an `after(:context)` hook:
```ruby
before(:context) do
@widget = Widget.create!
end
after(:context) do
@widget.destroy
end
```
If you don't do that, you'll leave data lying around that will eventually
interfere with other examples.
2. Reload the object in a `before(:example)` hook.
```ruby
before(:context) do
@widget = Widget.create!
end
before(:example) do
@widget.reload
end
```
Even though database updates in each example will be rolled back, the
object won't _know_ about those rollbacks so the object and its backing
data can easily get out of sync.
|