Kyle McVay
Kyle McVay

Reputation: 495

How do I completely avoid using a database in RSpec tests?

I want to use FactoryGirl to build in-memory stubs of models, then have all ActiveRecord queries run against only those. For example:

# Assume we start with an empty database, a Foo model, 
# and a Foo factory definition.

#foo_spec.rb
stubbed_foo = FactoryGirl.build_stubbed(:foo)

# Elsewhere, deep in the guts of application
Foo.first() # Ideally would return the stubbed_foo we created
            # in the test. Currently this returns nil.

The solution might be to use an in-memory database. But is the above scenario possible?

Upvotes: 4

Views: 1542

Answers (1)

Robin Daugherty
Robin Daugherty

Reputation: 7524

If your reason for avoiding the database, is to speed up your tests, then there are better ways.

Use FactoryGirl.build as much as possible instead of create. This works as long as the record won't be fetched from the database by your code. This works well for unit tests with well-structured code. (For example, it helps to use Service Objects and unit test them independently.

For tests that actually need to read from the database (as in your Foo.first example call), you can use FactoryGirl.create and use transactional fixtures. This creates a database transaction at the beginning of each test example, and then rolls back the transaction at the end of the example. This can cause problems when you use callbacks in your ActiveRecord models such as after_commit.

If you use after_commit or other callbacks in your models that require the database transaction to close (or you use explicit transactions in your code), I recommend setting up DatabaseCleaner. Here's an example of to configure and use it: https://gist.github.com/RobinDaugherty/9f4e5f782d9fdbe191a23de30ad8b539

Upvotes: 1

Related Questions