RSpec: how to run tests on a different database
Asked Answered
Y

2

0

I have to migrate some data and I'd like to test some models that use a different connection, i.e. other than one defined in database.yml develoment, test groups. So I added a new database connection to database.yml:

default: &default
  adapter: postgresql
  encoding: unicode
  user: postgres
  password:
  pool: 5

development:
  <<: *default
  database: myapp_development
  host: <%= ENV['DATABASE_HOST'] %>

test:
  <<: *default
  database: myapp_test
  host: <%= ENV['DATABASE_HOST'] %>

production:
  <<: *default
  host: <%= ENV['DATABASE_HOST'] %>
  database: myapp_production
  username: <%= ENV['DATABASE_USER'] %>
  password: <%= ENV['DATABASE_PASSWORD'] %>

mystore:
  adapter: oracle_enhanced
  host: <%= ENV['mystore_db_host']%>
  port: <%= ENV['mystore_db_port']%>
  database: <%= ENV['mystore_db_name']%>
  username: <%= ENV['mystore_db_user']%>
  password: <%= ENV['mystore_db_password']%>

Next, I creates a base model class in lib/mystore_migration folder:

module MystoreMigration
  class MystoreModel < ApplicationRecord
    self.abstract_class = true
    establish_connection(:mystore)
  end
end

Other model classes used by the rake task inherit the above MystoreMigration class.

Next, when I just tried to initialize one of the models that use mystore connection in RSpec test file:

MystoreMigration::ShopInfo.new(
      address: Faker::Address.street_address,
      address2: Faker::Address.street_name,
...
)

and run it, it failed:

OCIError:
  ORA-12162: TNS:net service name is incorrectly specified

It seems like RSpec tried to use another settings/database or whatever instead of the one I defined with establish_connection(:mystore).

If I add unless Rails.env.test? condition to establish_connection:

module MystoreMigration
  class MystoreModel < ApplicationRecord
    self.abstract_class = true
    establish_connection(:mystore) unless Rails.env.test?
  end
end

the error message is different and says it can'd set up relations:

ActiveRecord::StatementInvalid:
       PG::UndefinedTable: ERROR:  relation "STORE_INFO" does not exist
       LINE 8:                WHERE a.attrelid = '"STORE_INFO"'::regclass

As you see, in the first case, it tried to connect to Oracle database what is correct but it failed. In the second case it tried to connect to Postgresql database (wrong, as it is used in other environments than mystore).

If I run a rake task that uses mystore connection, it works, - running tests- fails. What's wrong with that ?

I'm using Rails 5.2.0, ruby 2.5.0, macOS. Thank you.

Yarrow answered 27/6, 2018 at 15:44 Comment(1)
Thanks for the tip on unless Rails.env.test? at establish_connection!Iata
Y
0

It seems like when running tests, Rails will query the database defined in test group in database.yml, - in my case it is myapp_test. But when querying the models using mystore connection, it will not find the corresponding tables, because there is no database connection defined for those models in test environment. It means that the only solution is to mock all the database requests for the models that use mystore connection.

Yarrow answered 13/7, 2018 at 7:35 Comment(0)
L
0

I had a similar problem and I think it can help someone that ends up here searching for an answer. I'm in RoR 5.2.2.

In my case when I did establish_connection to another database in a model it wasn't working in env test, but in other environments.

Alt 1. This wasn't working in test env

class AnotherConnection < ActiveRecord::Base
  self.abstract_class = true
  establish_connection(:another_db)
end

Alt 2. I came up with this solution, inspired from this anwser

class AnotherConnection < ActiveRecord::Base
  self.abstract_class = true
  class << self
    def connection
      @connection_x ||=
        establish_connection(:another_db).connection
    end
  end
end

The @connection_x is because I don't want to interfere with any existing (class) instance variables in RoR.

In both cases AnotherConnection.connection_config was showing the "other database", but in Alt 1. it was still using the "main" database when doing queries. And this was only a problem in test (with RSpec). In development env both alternatives work.

Lepanto answered 28/10, 2022 at 18:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.