specs for multi orms/connections and some implementation

This commit is contained in:
Jon Rowe 2010-03-30 22:49:30 +01:00
parent ebb6377fe5
commit f7858cd501
3 changed files with 352 additions and 103 deletions

View file

@ -38,6 +38,45 @@ module DatabaseCleaner
end end
class << self class << self
def [](orm)
raise NoORMDetected if orm.nil?
DatabaseCleaner::Base.new(orm)
end
def connections
@connections ||= [::DatabaseCleaner::Base.new]
end
def strategy=(stratagem)
self.connections.first.strategy = stratagem
end
def orm=(orm)
self.connections.first.orm = orm
end
def start
self.connections.first.start
end
def clean
self.connections.first.clean
end
def clean_with(stratagem)
self.connections.first.clean_with stratagem
end
end
class Base
def initialize(desired_orm = nil)
if desired_orm == :autodetect || desired_orm.nil?
autodetect
else
self.orm = desired_orm
end
end
def create_strategy(*args) def create_strategy(*args)
strategy, *strategy_args = args strategy, *strategy_args = args
@ -63,8 +102,8 @@ module DatabaseCleaner
end end
end end
def orm=(orm_string) def orm=(desired_orm)
@orm = orm_string @orm = desired_orm
end end
def start def start
@ -77,6 +116,14 @@ module DatabaseCleaner
alias clean! clean alias clean! clean
def orm
@orm || autodetect
end
def auto_detected
return true unless @autodetected.nil?
end
private private
def strategy def strategy
@ -84,44 +131,46 @@ module DatabaseCleaner
raise NoStrategySetError, "Please set a strategy with DatabaseCleaner.strategy=." raise NoStrategySetError, "Please set a strategy with DatabaseCleaner.strategy=."
end end
def orm_module
::DatabaseCleaner.orm_module(orm)
end
def orm_strategy(strategy) def orm_strategy(strategy)
require "database_cleaner/#{orm}/#{strategy}" require "database_cleaner/#{orm.to_s}/#{strategy.to_s}"
orm_module.const_get(strategy.to_s.capitalize) orm_module.const_get(strategy.to_s.capitalize)
rescue LoadError => e rescue LoadError => e
raise UnknownStrategySpecified, "The '#{strategy}' strategy does not exist for the #{orm} ORM! Available strategies: #{orm_module.available_strategies.join(', ')}" raise UnknownStrategySpecified, "The '#{strategy}' strategy does not exist for the #{orm} ORM! Available strategies: #{orm_module.available_strategies.join(', ')}"
end end
def autodetect
def orm
@orm ||= begin @orm ||= begin
@autodetected = true
if defined? ::ActiveRecord if defined? ::ActiveRecord
'active_record' :active_record
elsif defined? ::DataMapper elsif defined? ::DataMapper
'data_mapper' :data_mapper
elsif defined? ::MongoMapper elsif defined? ::MongoMapper
'mongo_mapper' :mongo_mapper
elsif defined? ::CouchPotato elsif defined? ::CouchPotato
'couch_potato' :couch_potato
else else
raise NoORMDetected, "No known ORM was detected! Is ActiveRecord, DataMapper, MongoMapper or CouchPotato loaded?" raise NoORMDetected, "No known ORM was detected! Is ActiveRecord, DataMapper, MongoMapper or CouchPotato loaded?"
end end
end end
end end
def orm_module def orm_module
case orm case orm
when 'active_record' when :active_record
DatabaseCleaner::ActiveRecord DatabaseCleaner::ActiveRecord
when 'data_mapper' when :data_mapper
DatabaseCleaner::DataMapper DatabaseCleaner::DataMapper
when 'mongo_mapper' when :mongo_mapper
DatabaseCleaner::MongoMapper DatabaseCleaner::MongoMapper
when 'couch_potato' when :couch_potato
DatabaseCleaner::CouchPotato DatabaseCleaner::CouchPotato
end end
end end
end end
end end

View file

@ -19,76 +19,190 @@ describe DatabaseCleaner do
end end
end end
# These examples muck around with the constants for autodetection so we need to clean up.... context "orm specification" do
before(:all) do
TempAR = ActiveRecord unless defined?(TempAR) it "should not accept unrecognised orms" do
TempMM = MongoMapper unless defined?(TempMM) lambda { ::DatabaseCleaner[nil] }.should raise_error ::DatabaseCleaner::NoORMDetected
Object.send(:remove_const, 'MongoMapper') if defined?(::MongoMapper)
# need to add one for each ORM that we load in the spec helper...
end end
after(:all) do
Object.send(:remove_const, 'ActiveRecord') if defined?(::ActiveRecord) #want to make sure we have the real one... it "should accept :active_record" do
ActiveRecord = TempAR cleaner = ::DatabaseCleaner[:active_record]
MongoMapper = TempMM cleaner.should be_a ::DatabaseCleaner::Base
cleaner.orm.should == :active_record
end
it "should accept :data_mapper" do
cleaner = ::DatabaseCleaner[:data_mapper]
cleaner.should be_a ::DatabaseCleaner::Base
cleaner.orm.should == :data_mapper
end
it "should accept :mongo_mapper" do
cleaner = ::DatabaseCleaner[:mongo_mapper]
cleaner.should be_a ::DatabaseCleaner::Base
cleaner.orm.should == :mongo_mapper
end
it "should accept :couch_potato" do
cleaner = ::DatabaseCleaner[:couch_potato]
cleaner.should be_a ::DatabaseCleaner::Base
cleaner.orm.should == :couch_potato
end
end
context "class methods" do
it "should have array of connections (orm agnostic)" do
::DatabaseCleaner.connections.should respond_to(:each)
end
it "should give me a default (autodetection) databasecleaner by default" do
::DatabaseCleaner.connections.should have (1).items
::DatabaseCleaner.connections.first.should be_a ::DatabaseCleaner::Base
end
end
context "instance methods" do
it "should default to autodetect upon initalisation" do
cleaner = ::DatabaseCleaner::Base.new
cleaner.auto_detected.should == true
end
context "autodetect" do
before(:all) do
Temp_AR = ActiveRecord if defined?(::ActiveRecord) and not defined?(Temp_AR)
Temp_DM = DataMapper if defined?(::DataMapper) and not defined?(Temp_DM)
Temp_MM = MongoMapper if defined?(::MongoMapper) and not defined?(Temp_MM)
Temp_CP = CouchPotato if defined?(::CouchPotato) and not defined?(Temp_CP)
end end
before(:each) do before(:each) do
DatabaseCleaner::ActiveRecord::Transaction.stub!(:new).and_return(@strategy = mock('strategy')) # Remove ORM consts for these tests
Object.const_set('ActiveRecord', "just mocking out the constant here...") unless defined?(::ActiveRecord) Object.send(:remove_const, 'ActiveRecord') if defined?(::ActiveRecord)
DatabaseCleaner.strategy = nil Object.send(:remove_const, 'DataMapper') if defined?(::DataMapper)
DatabaseCleaner.orm = nil Object.send(:remove_const, 'MongoMapper') if defined?(::MongoMapper)
Object.send(:remove_const, 'CouchPotato') if defined?(::CouchPotato)
end
it "should raise an error when no ORM is detected" do
running { DatabaseCleaner::Base.new(:autodetect) }.should raise_error(DatabaseCleaner::NoORMDetected)
end
it "should detect ActiveRecord first" do
Object.const_set('ActiveRecord','Actively mocking records.')
Object.const_set('DataMapper', 'Mapping data mocks')
Object.const_set('MongoMapper', 'Mapping mock mongos')
Object.const_set('CouchPotato', 'Couching mock potatos')
cleaner = DatabaseCleaner::Base.new :autodetect
cleaner.orm.should == :active_record
end
it "should detect DataMapper second" do
Object.const_set('DataMapper', 'Mapping data mocks')
Object.const_set('MongoMapper', 'Mapping mock mongos')
Object.const_set('CouchPotato', 'Couching mock potatos')
cleaner = DatabaseCleaner::Base.new :autodetect
cleaner.orm.should == :data_mapper
end
it "should detect MongoMapper third" do
Object.const_set('MongoMapper', 'Mapping mock mongos')
Object.const_set('CouchPotato', 'Couching mock potatos')
cleaner = DatabaseCleaner::Base.new :autodetect
cleaner.orm.should == :mongo_mapper
end
it "should detect CouchPotato last" do
Object.const_set('CouchPotato', 'Couching mock potatos')
cleaner = DatabaseCleaner::Base.new :autodetect
cleaner.orm.should == :couch_potato
end
after(:all) do
Object.send(:remove_const, 'ActiveRecord') if defined?(::ActiveRecord)
Object.send(:remove_const, 'DataMapper') if defined?(::DataMapper)
Object.send(:remove_const, 'MongoMapper') if defined?(::MongoMapper)
Object.send(:remove_const, 'CouchPotato') if defined?(::CouchPotato)
# Restore ORMs
ActiveRecord = Temp_AR if defined? Temp_AR
DataMapper = Temp_DM if defined? Temp_DM
MongoMapper = Temp_MM if defined? Temp_MM
CouchPotato = Temp_CP if defined? Temp_CP
end
end
end
context "single orm" do
let (:connection) { ::DatabaseCleaner.connections.first }
it "should proxy strategy=" do
stratagum = mock("stratagum")
connection.should_receive(:strategy=).with(stratagum)
::DatabaseCleaner.strategy = stratagum
end
it "should proxy orm=" do
orm = mock("orm")
connection.should_receive(:orm=).with(orm)
::DatabaseCleaner.orm = orm
end
it "should proxy start" do
connection.should_receive(:start)
::DatabaseCleaner.start
end
it "should proxy clean" do
connection.should_receive(:clean)
::DatabaseCleaner.clean
end
it "should proxy clean_with" do
stratagem = mock("stratgem")
connection.should_receive(:clean_with).with(stratagem)
::DatabaseCleaner.clean_with stratagem
end
end
describe ::DatabaseCleaner::Base do
describe "orm_module" do
it "should proxy to the class method"
end
let(:strategy) { mock("stratagum") }
context "active record" do
let(:cleaner) { ::DatabaseCleaner::Base.new(:active_record) }
before(:each) do
::DatabaseCleaner::ActiveRecord::Transaction.stub!(:new).and_return(strategy)
#Object.const_set('ActiveRecord', "just mocking out the constant here...") unless defined?(::ActiveRecord)
cleaner.strategy = nil
end end
describe ".create_strategy" do describe ".create_strategy" do
it "should initialize and return the appropirate strategy" do it "should initialize and return the appropirate strategy" do
DatabaseCleaner::ActiveRecord::Transaction.should_receive(:new).with('options' => 'hash') DatabaseCleaner::ActiveRecord::Transaction.should_receive(:new).with('options' => 'hash')
result = DatabaseCleaner.create_strategy(:transaction, {'options' => 'hash'}) result = cleaner.create_strategy(:transaction, {'options' => 'hash'})
result.should == @strategy result.should == strategy
end end
end end
describe ".clean_with" do describe ".clean_with" do
it "should initialize the appropirate strategy and clean with it" do it "should initialize the appropirate strategy and clean with it" do
DatabaseCleaner::ActiveRecord::Transaction.should_receive(:new).with('options' => 'hash') DatabaseCleaner::ActiveRecord::Transaction.should_receive(:new).with('options' => 'hash')
@strategy.should_receive(:clean) strategy.should_receive(:clean)
DatabaseCleaner.clean_with(:transaction, 'options' => 'hash') cleaner.clean_with(:transaction, 'options' => 'hash')
end end
end end
describe ".strategy=" do describe ".strategy=" do
it "should initialize the appropirate strategy based on the ORM adapter detected" do it "should initialize the appropirate strategy for active record" do
DatabaseCleaner::ActiveRecord::Transaction.should_receive(:new).with('options' => 'hash') DatabaseCleaner::ActiveRecord::Transaction.should_receive(:new).with('options' => 'hash')
DatabaseCleaner.strategy = :transaction, {'options' => 'hash'} cleaner.strategy = :transaction, {'options' => 'hash'}
Object.send(:remove_const, 'ActiveRecord')
Object.const_set('DataMapper', "just mocking out the constant here...")
DatabaseCleaner.orm = nil
DatabaseCleaner::DataMapper::Transaction.should_receive(:new).with(no_args)
DatabaseCleaner.strategy = :transaction
end
it "should raise an error when no ORM is detected" do
Object.send(:remove_const, 'ActiveRecord') if defined?(::ActiveRecord)
Object.send(:remove_const, 'DataMapper') if defined?(::DataMapper)
Object.send(:remove_const, 'CouchPotato') if defined?(::CouchPotato)
running { DatabaseCleaner.strategy = :transaction }.should raise_error(DatabaseCleaner::NoORMDetected)
end
it "should use the strategy version of the ORM specified with #orm=" do
DatabaseCleaner.orm = 'data_mapper'
DatabaseCleaner::DataMapper::Transaction.should_receive(:new)
DatabaseCleaner.strategy = :transaction
end
it "should raise an error when multiple args is passed in and the first is not a symbol" do
running { DatabaseCleaner.strategy=Object.new, {:foo => 'bar'} }.should raise_error(ArgumentError)
end
it "should raise an error when the specified strategy is not found" do
running { DatabaseCleaner.strategy = :foo }.should raise_error(DatabaseCleaner::UnknownStrategySpecified)
end end
it "should allow any object to be set as the strategy" do it "should allow any object to be set as the strategy" do
@ -96,23 +210,108 @@ describe DatabaseCleaner do
running { DatabaseCleaner.strategy = mock_strategy }.should_not raise_error running { DatabaseCleaner.strategy = mock_strategy }.should_not raise_error
end end
it "should raise an error when the specified strategy is not found" do
running { DatabaseCleaner.strategy = :foo }.should raise_error(DatabaseCleaner::UnknownStrategySpecified)
end end
it "should raise an error when multiple args is passed in and the first is not a symbol" do
running { DatabaseCleaner.strategy=Object.new, {:foo => 'bar'} }.should raise_error(ArgumentError)
end
end
%w[start clean].each do |strategy_method| %w[start clean].each do |strategy_method|
describe ".#{strategy_method}" do describe ".#{strategy_method}" do
it "should be delgated to the strategy set with strategy=" do it "should be delgated to the strategy set with strategy=" do
DatabaseCleaner.strategy = :transaction cleaner.strategy = :transaction
@strategy.should_receive(strategy_method) strategy.should_receive(strategy_method)
DatabaseCleaner.send(strategy_method) cleaner.send(strategy_method)
end end
it "should raise en error when no strategy has been set" do it "should raise en error when no strategy has been set" do
running { DatabaseCleaner.send(strategy_method) }.should raise_error(DatabaseCleaner::NoStrategySetError) running { cleaner.send(strategy_method) }.should raise_error(DatabaseCleaner::NoStrategySetError)
end
end end
end end
end end
context "data mapper" do
let(:cleaner) { ::DatabaseCleaner::Base.new(:data_mapper) }
before(:each) do
::DatabaseCleaner::DataMapper::Transaction.stub!(:new).and_return(strategy)
#Object.const_set('ActiveRecord', "just mocking out the constant here...") unless defined?(::ActiveRecord)
cleaner.strategy = nil
end
describe ".create_strategy" do
it "should initialize and return the appropirate strategy" do
DatabaseCleaner::DataMapper::Transaction.should_receive(:new)
result = cleaner.create_strategy(:transaction)
result.should == strategy
end
end
describe ".clean_with" do
it "should initialize the appropirate strategy and clean with it" do
DatabaseCleaner::DataMapper::Transaction.should_receive(:new)
strategy.should_receive(:clean)
cleaner.clean_with(:transaction)
end
end
describe ".strategy=" do
it "should initalize the appropriate strategy for data mapper" do
DatabaseCleaner::DataMapper::Transaction.should_receive(:new).with(no_args)
cleaner.strategy = :transaction
end
it "should allow any object to be set as the strategy" do
mock_strategy = mock('strategy')
running { cleaner.strategy = mock_strategy }.should_not raise_error
end
it "should raise an error when the specified strategy is not found" do
running { cleaner.strategy = :foo }.should raise_error(DatabaseCleaner::UnknownStrategySpecified)
end
it "should raise an error when multiple args is passed in and the first is not a symbol" do
running { cleaner.strategy=Object.new, {:foo => 'bar'} }.should raise_error(ArgumentError)
end
end
%w[start clean].each do |strategy_method|
describe ".#{strategy_method}" do
it "should be delgated to the strategy set with strategy=" do
cleaner.strategy = :transaction
strategy.should_receive(strategy_method)
cleaner.send(strategy_method)
end
it "should raise en error when no strategy has been set" do
running { cleaner.send(strategy_method) }.should raise_error(DatabaseCleaner::NoStrategySetError)
end
end
end
end
# it "should raise an error when no ORM is detected" do
# Object.send(:remove_const, 'ActiveRecord') if defined?(::ActiveRecord)
# Object.send(:remove_const, 'DataMapper') if defined?(::DataMapper)
# Object.send(:remove_const, 'CouchPotato') if defined?(::CouchPotato)
#
# running { DatabaseCleaner.strategy = :transaction }.should raise_error(DatabaseCleaner::NoORMDetected)
# end
# it "should use the strategy version of the ORM specified with #orm=" do
# DatabaseCleaner.orm = 'data_mapper'
# DatabaseCleaner::DataMapper::Transaction.should_receive(:new)
#
# DatabaseCleaner.strategy = :transaction
# end
end
end end

View file

@ -4,3 +4,4 @@
mtime mtime
--reverse --reverse
--backtrace --backtrace
--debugger