Skip to content

Instantly share code, notes, and snippets.

@ClayShentrup
Created January 22, 2021 19:41
Show Gist options
  • Save ClayShentrup/c8bc73db185a82f4565de387e071710a to your computer and use it in GitHub Desktop.
Save ClayShentrup/c8bc73db185a82f4565de387e071710a to your computer and use it in GitHub Desktop.
Some fake db testing techniques I've used a bunch
# frozen_string_literal: true
RSpec.shared_context('customer_records') do
let!(:customer_record_model) do
stub_const('CustomerRecord', Class.new(AbstractCustomerRecord))
.tap { |model| model.establish_connection(test_db) }
end
let!(:customer_record_factory) do
FactoryBot::Factory.new(:customer_record)
end
attr_reader(:test_db)
end
# Base class so we can make a customer_record model that runs on the test
# customer database instead of our actual test database whose schema we don't
# want to mess up.
class AbstractCustomerRecord < ActiveRecord::Base
self.abstract_class = true
class << self
def establish_connection(test_db)
super(
adapter: test_db.adapter,
database: test_db.database,
host: test_db.host,
port: test_db.port,
username: test_db.username,
password: test_db.password,
)
end
end
end
RSpec.shared_context('with postgres origin db') do
let(:database_type) { 'postgres' }
append_before do |example|
assign_database_cleaner_strategy_for_model(
customer_record_model,
example.metadata,
)
end
def prepare_database; end
before(:all) do
@test_db = CreateTestPostgresCustomerDatabase.call
end
after(:all) do
test_db.teardown
end
end
# Creates and launches a new disposable Postgres DB in /tmp, so we don't mess
# up our test DB schema for simulating Yoinkitron interactions with customer
# databases.
class CreateTestPostgresCustomerDatabase < MethodObject
def call
create_customer_records_table
TestPostgresDatabase.new(pg_tester)
end
def pg_tester
@pg_tester ||= PgTester.new(data_dir: Dir.mktmpdir).tap(&:setup)
end
def create_customer_records_table
pg_tester.exec(<<~SQL)
CREATE TABLE customer_records (
id SERIAL PRIMARY KEY,
created_at timestamp without time zone,
updated_at timestamp without time zone,
title character varying(255)
)
SQL
end
end
# Presenter for a PgTester instance, providing names that match the ActiveRecord
# `establish_connection` keyword args
class TestPostgresDatabase
def initialize(pg_tester)
@pg_tester = pg_tester
end
delegate(:database, :host, :port, :teardown, to: :pg_tester)
def adapter
'postgresql'
end
def username
@pg_tester.user
end
def password
''
end
private
attr_reader(:pg_tester)
end
RSpec.shared_context('with redshift origin db') do
let(:database_type) { 'redshift' }
before(:all) do
@test_db = TestRedshiftDatabase.new
end
def prepare_database
create_customer_records_table
end
after do
drop_customer_records_table
end
def create_customer_records_table
CustomerRecord.connection.execute(<<~SQL)
CREATE TABLE customer_records (
id integer PRIMARY KEY,
created_at timestamp without time zone,
updated_at timestamp without time zone,
title character varying(255)
)
SQL
end
def drop_customer_records_table
CustomerRecord.connection.execute(<<~SQL)
DROP TABLE customer_records;
SQL
end
end
# Presenter for a redshift instance, providing names that match the ActiveRecord
# `establish_connection` keyword args
class TestRedshiftDatabase
def database
'datebase_name'
end
def host
'hostname'
end
def port
5439
end
def adapter
'redshift'
end
def username
'joe_black'
end
def password
ScopeEnv.get('DEV_SHARED_REDSHIFT_PASSWORD')
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment