Rspec Using Development Database
Asked Answered
P

7

12

I am using Rails 4.2 with Ruby 2.2 and rspec for testcases. I have set

Rails.env = 'test'

in both my spec_helper and rails_helper. Here is my database.yml file:

development:
  adapter: postgresql
  encoding: unicode
  database: app_dev
  pool: 5
  username: postgres
  password: root

test:
  adapter: postgresql
  encoding: unicode
  database: app_test
  pool: 5
  username: postgres
  password: root

production:
  adapter: postgresql
  encoding: unicode
  database: app_prod
  pool: 5
  username: postgres
  password: root

Here is my rails_helper:

Rails.env = 'test'
require 'spec_helper'
require File.expand_path('../../config/environment', __FILE__)
require 'rspec/rails'
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|
  config.include JsonHelper
  config.include PathHelper
  config.include S3Helper
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = true
  config.infer_spec_type_from_file_location!
end

application.rb:

require File.expand_path('../boot', __FILE__)

require 'rails/all'
require 'yaml'
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module AppName
  class Application < Rails::Application
    config.generators do |g|
      g.assets = false
      g.helper = false
      g.views = false
    end

    # Load all locale files
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
    config.i18n.load_path += Dir[Rails.root.join(
                              'config', 'locales', '**', '**', '*.{rb,yml}')]
    config.autoload_paths += %W(#{config.root}/lib)
    config.autoload_paths += Dir["#{config.root}/lib/**/"]
    config.autoload_paths += Dir["#{config.root}/app/workers/"]
    config.action_controller.include_all_helpers = false
    config.active_record.schema_format           = :sql
    config.i18n.available_locales = [:en, :hi, :mr]
    config.i18n.default_locale = :hi
    config.i18n.fallbacks = [:en]
    config.active_record.raise_in_transactional_callbacks = true
  end
end

Gemfile:

source 'https://rubygems.org'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.0'

# Use postgresql as the database for Active Record
gem 'pg', '~> 0.18.2'

# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'

# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'

# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.1.0'
# Turbolinks makes following links in your web application faster
gem 'turbolinks', '~> 2.5.3'

# Use Unicorn as the app server
gem 'unicorn', '~> 4.9.0'

# Use jquery as the JavaScript library
gem 'jquery-rails', '~> 4.0.4'

# Integrate the jQuery Validation plugin into the Rails asset pipeline
gem 'jquery-validation-rails', '~> 1.13.1'

# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'

# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc

# use swagger for api documentation
gem 'swagger-docs', '~> 0.1.9'

# for consuming restful web services
gem 'httparty', '~> 0.13.5'

# for ActiveRecord model/data translations
gem 'globalize', '~> 5.0.0'

# generates accessors for translated fields
gem 'globalize-accessors', '~>0.2.1'

# Amazon Web service SDK Ruby
gem 'aws-sdk', '~> 2.1.0'

# cloud services for S3
gem 'fog', '~> 1.33.0'

# handle file uploads
gem 'carrierwave', '~>0.10.0'

# Photo Resizing
gem 'mini_magick', '~> 4.2.7'

# Background Jobs
gem 'sidekiq', '~> 3.4.2'

# Geocoder
gem 'geocoder', '~> 1.2.9'

# active admin
gem 'activeadmin', '~> 1.0.0.pre1'

# for authentication
gem 'devise', '~> 3.5.1'

# for roles of active admin
gem 'rolify', '~> 4.0.0'

# for authorization
gem 'cancan', '~> 1.6.10'

group :development, :test do
  # Debugging using pry
  gem 'pry-rails', '~> 0.3.4'
  gem 'pry-byebug', '~> 3.1.0'

  # testing framework for rails
  gem 'rspec-rails', '~> 3.1.0'
  gem 'rspec-collection_matchers', '~> 1.1.2'
  gem 'factory_girl_rails', '~> 4.4.1'
  gem 'shoulda-matchers', '~> 2.8.0'

  # code test coverage
  gem 'simplecov', '~> 0.7.1'
  gem 'simplecov-rcov', '~> 0.2.3'
  # Access an IRB console on exception pages or by using <%= console %> in views
  gem 'web-console', '~> 2.0'

  # speeds up development by keeping your application running in the background
  gem 'spring', '~> 1.3.6'
end

group :development do
  # generates ER diagrams for rails application
  gem 'rails-erd', '~> 1.4.1'
end

group :test do
  # set of strategies for cleaning your database
  gem 'database_cleaner', '~> 1.3.0'
end

When I run my test cases, Rails.env is 'test' as expected (used pry to verify). However my test cases are always hitting the development database.

Rails.env
#=> "test"

ActiveRecord::Base.connection_config
#=> {:adapter=>"postgresql", :encoding=>"unicode", :database=>"app_dev", :pool=>5, :username=>"postgres", :password=>"root"}

spec_helper:

require File.expand_path('../../config/environment', __FILE__)
require 'rspec/rails'
require 'simplecov'
require 'simplecov-rcov'
require 'database_cleaner'
require 'factory_girl_rails'

ENV['RAILS_ENV'] ||= 'test'
SimpleCov.start

RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
  # Database Cleaner
  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
    Rails.application.load_seed
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

  config.expect_with :rspec do |expectations|
    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
  end

  config.mock_with :rspec do |mocks|
    mocks.verify_partial_doubles = true
  end
end

SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter

I have been scratching my head since last few hours but nothing seems to solve the mystery. Any help would be greatful!

Petry answered 11/9, 2015 at 12:56 Comment(10)
Is it actually saving information to your dev db? Have you tried restarting your server?Preachy
@WesFoster : Yes. I did restart my server too. I have a users table with unique constraint on mobile_number. When I saw my test case failing, I used Pry and did a User.all. It showed up all my users in my dev database. Same for other tables also.Petry
And how do you verify that your test hits development db?Auroora
Can you debug this ActiveRecord::Base.connection_config ?Auroora
@dimakura: I am updating my question with these details. Thanks :)Petry
What happens if you remove your dev database from your database.yml file and restart?Risley
@Risley : Error on running rspec 'development' database is not configured. Available: ["test", "production"] (ActiveRecord::AdapterNotSpecified)Petry
If you add ActiveRecord::Base.establish_connection to your rails_helper does that help?Risley
@Yule: Something that finally works. It correclty sets my db to app_test when running rspec! Thanks a lot. Can you also explain me why do I have to explicitly establish_connection to make my rspec work correctly?Petry
Since Rails 7 use ActiveRecord::Base.connection_db_config instead of ActiveRecord::Base.connection_config (this one is deprecated)Ywis
R
8

It sounds as though somewhere in your environment (maybe one of your gems) it is setting your environment to dev or establishing a connection to your dev database.

To explicitly make it connect to the test database, add:

ActiveRecord::Base.establish_connection

to your rails_helper.

Prime candidate for troublemaker would be `gem 'rails-erd', '~> 1.4.1'. If you have this as auto-generating the diagram on migrate, when the test schema is migrated, it will connect to the dev database to dump a diagram.

Try removing this gem or perhaps the '.rake' file and see what happens.

Risley answered 14/9, 2015 at 10:23 Comment(6)
Thanks You :) Your answer did help me correctly set the database to test database. However I am still a little doubtful for the reasoning behind your answer. I will wait for some time more for a clearer answer else will mark your answer as accepted. Thanks a lot for looking into it. Please let me know if you require more details/file to debug on the odd behaviour of rails_helperPetry
I'm glad I can help, and given I solved the issue - an upvote wouldn't go astray ;). Unfortunately it's impossible to say why this is needed as the code in your question does not give a reproducible instance. i.e. if i start a new rails project with nothing but your rails_helper, rspec and one test - I do not get the same issue. So the problem is elsewhere. Likely application.rb or one of your gems. Can you show these?Risley
agreed and upvoted :). Also updated my question with application.rb and gemfile.Petry
It is not the rails-erd gem which is causing the problem. I removed the gem and tested and got the same problem. I am adding my spec_helper file too if that helps.Petry
I have marked it as answer because it came the closest to my question and the bounty was closing today. However the reasoning is still missing. thanks :)Petry
This doesn't work for me. I added ENV["RAILS_ENV"] ||= 'test' in spec_helper.rb and it works 😕Behest
B
13

The reason your tests hit the development database is because you have defined ENV['DATABASE_URL'] somewhere in your environment.

There are two ways of specifying the database connection to be used:

  1. Specifying the ENV['DATABASE_URL']
  2. Using the very popular database.yml file

In many cases the first one takes prescedence over the latter.

I realized I had a problem similar to yous after using ENV['DATABASE_URL'] to set my production database, only to find out that all my environments (test & development) suddenly had started to use my production database regardless of content in database.yml.

To solve my problem all I did was change the name on the environment variable to something else, so that it no longer overwrite my database.yml configurations.

Reading this will solve your problem: Connection Preference information

Babism answered 24/3, 2018 at 20:33 Comment(3)
In my case, this was the correct answer. Thanks a lot.Bivalent
Thanks for saving me. I have been looking for an answer for a month.Prorogue
Their 'automatic merging' is really unexpected, thanks for explanation!Ywis
R
8

It sounds as though somewhere in your environment (maybe one of your gems) it is setting your environment to dev or establishing a connection to your dev database.

To explicitly make it connect to the test database, add:

ActiveRecord::Base.establish_connection

to your rails_helper.

Prime candidate for troublemaker would be `gem 'rails-erd', '~> 1.4.1'. If you have this as auto-generating the diagram on migrate, when the test schema is migrated, it will connect to the dev database to dump a diagram.

Try removing this gem or perhaps the '.rake' file and see what happens.

Risley answered 14/9, 2015 at 10:23 Comment(6)
Thanks You :) Your answer did help me correctly set the database to test database. However I am still a little doubtful for the reasoning behind your answer. I will wait for some time more for a clearer answer else will mark your answer as accepted. Thanks a lot for looking into it. Please let me know if you require more details/file to debug on the odd behaviour of rails_helperPetry
I'm glad I can help, and given I solved the issue - an upvote wouldn't go astray ;). Unfortunately it's impossible to say why this is needed as the code in your question does not give a reproducible instance. i.e. if i start a new rails project with nothing but your rails_helper, rspec and one test - I do not get the same issue. So the problem is elsewhere. Likely application.rb or one of your gems. Can you show these?Risley
agreed and upvoted :). Also updated my question with application.rb and gemfile.Petry
It is not the rails-erd gem which is causing the problem. I removed the gem and tested and got the same problem. I am adding my spec_helper file too if that helps.Petry
I have marked it as answer because it came the closest to my question and the bounty was closing today. However the reasoning is still missing. thanks :)Petry
This doesn't work for me. I added ENV["RAILS_ENV"] ||= 'test' in spec_helper.rb and it works 😕Behest
A
5

Your rails_helper looks strange. The first line says:

Rails.env = 'test'

At the first line you don't have Rails loaded yet (I suppose you run RSpec using bundle exec rspec). So it should raise an error.

Therefore I made a small change in rails_helper:

require File.expand_path('../../config/environment', __FILE__)
Rails.env = 'test'
require 'spec_helper'
require 'rspec/rails'
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

# the rest

Now putting

expect(ActiveRecord::Base.connection_config[:database]).to match(/test/)

somewhere in your spec, should pass successfully.

Auroora answered 11/9, 2015 at 13:30 Comment(8)
I already have a Rails.env = 'test' in my rails helper (mentioned it in my question above). Earlier i had a ENV['RAILS_ENV'] ||= 'test' in my rails_helper and it did not set my env correclty. Hence I changed it to Rails.env = 'test' after suggestions on SO. (That helped. My env is now set correctly for test cases.) But it still hits the dev db and not test db.Petry
Can you add ENV['RAILS_ENV'] ||= 'test' just for checking in the first line? And where is Rails.env=test defined? Can you give full rails_helper.rb?Auroora
Sure. I am adding rails_helper.rb in the question above. Thank you :)Petry
setting ` ENV['RAILS_ENV'] ||= 'test'` as first line of my rails_helper does not help. Instead it shows my 'Rails.env' shows as 'development' when I run Rspec (checked using pry)Petry
@AaditiJain I've updated my answer. But I'm curious how do you invoke RSpec?Auroora
I use rspec command to run my test cases. Also I tried solution mentioned in your answer but it does not solve the problem.Petry
@AaditiJain So you clain expect(ActiveRecord::Base.connection_config[:database]).to match(/test/) did not pass?Auroora
No it did not. Got this: Failure/Error: expect(ActiveRecord::Base.connection_config[:database]).to match(/test/) expected "app_dev" to match /test/ Diff: @@ -1,2 +1,2 @@ -/test/ +"app_dev"Petry
E
2

My answer applies to anyone who is using Rspec with Ruby outside of Rails. For example, let's say you are creating a Ruby gem. Well, you can still add a database.yml in a config folder in your project and specify a test option:

test:
  adapter: 'mysql2'
  encoding: utf8mb4
  collation: utf8mb4_bin
  pool: 1
  username: root
  password:
  host: localhost
  database: 'my_site_test'

Now you can add the following in spec_helper.rb:

  config.before :suite do
    ActiveRecord::Base.establish_connection(YAML.load(File.open(File.expand_path("../../lib/my_gem_config/database.yml", __FILE__)))["test"])
  end  

The :suite scope indicates that the block of code should be run once before the suite of tests, that means all of your tests.

Ermaermanno answered 27/6, 2018 at 0:27 Comment(1)
This is the only solution that works for me but I don't understand why I need to call it at all!Prolegomenon
M
1

1) Add require: false to the declaration of 'rails-erd' gem

gem 'rails-erd', '~> 1.4.1', require: false

2) In your spec_helper.rb, replace Rails.env = 'test' by ENV['RAILS_ENV'] ||= 'test'

3) Verify in your bin/rspec (if present) that you don't have any instruction changing the value of env

4) Then stop spring from the command line

spring stop

5) Run your specs from the command line

rspec
Machiavelli answered 16/9, 2015 at 6:29 Comment(0)
M
1

You can run rspc with RAILS_ENV=test bundle exec rspec spec

Also you can put inside rails_helper.rb

Rails.env = 'test'

Also move testing framework section from development test to test inside gemfile

group :test do
  # testing framework for rails
  gem 'rspec-rails', '~> 3.1.0'
  gem 'rspec-collection_matchers', '~> 1.1.2'
  gem 'factory_girl_rails', '~> 4.4.1'
  gem 'shoulda-matchers', '~> 2.8.0'

  # set of strategies for cleaning your database
  gem 'database_cleaner', '~> 1.3.0'
end
Microbe answered 20/9, 2015 at 19:26 Comment(0)
A
0

Just put ENV["RAILS_ENV"] = "test" at the top of rails_helper

Archiepiscopate answered 14/9, 2015 at 9:51 Comment(1)
No, that does not help :( . Also, as I have mentioned in the question, my Rails.env is set correctly to test during rspec (verified using pry). Thanks for looking :)Petry

© 2022 - 2024 — McMap. All rights reserved.