nulldb 0.3.7.pre.alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +28 -0
  3. data/.travis.yml +49 -0
  4. data/Appraisals +36 -0
  5. data/CHANGES.md +75 -0
  6. data/Gemfile +14 -0
  7. data/LICENSE +21 -0
  8. data/README.rdoc +147 -0
  9. data/Rakefile +14 -0
  10. data/VERSION +1 -0
  11. data/gemfiles/activerecord_2.3.gemfile +17 -0
  12. data/gemfiles/activerecord_3.0.gemfile +16 -0
  13. data/gemfiles/activerecord_3.1.gemfile +16 -0
  14. data/gemfiles/activerecord_3.2.gemfile +16 -0
  15. data/gemfiles/activerecord_4.0.gemfile +16 -0
  16. data/gemfiles/activerecord_4.1.gemfile +16 -0
  17. data/gemfiles/activerecord_4.2.gemfile +16 -0
  18. data/gemfiles/activerecord_5.0.gemfile +16 -0
  19. data/gemfiles/activerecord_5.1.gemfile +16 -0
  20. data/gemfiles/activerecord_master.gemfile +18 -0
  21. data/lib/active_record/connection_adapters/nulldb_adapter.rb +21 -0
  22. data/lib/active_record/connection_adapters/nulldb_adapter/checkpoint.rb +13 -0
  23. data/lib/active_record/connection_adapters/nulldb_adapter/column.rb +20 -0
  24. data/lib/active_record/connection_adapters/nulldb_adapter/configuration.rb +5 -0
  25. data/lib/active_record/connection_adapters/nulldb_adapter/core.rb +324 -0
  26. data/lib/active_record/connection_adapters/nulldb_adapter/empty_result.rb +26 -0
  27. data/lib/active_record/connection_adapters/nulldb_adapter/index_definition.rb +5 -0
  28. data/lib/active_record/connection_adapters/nulldb_adapter/null_object.rb +13 -0
  29. data/lib/active_record/connection_adapters/nulldb_adapter/statement.rb +15 -0
  30. data/lib/active_record/connection_adapters/nulldb_adapter/table_definition.rb +5 -0
  31. data/lib/activerecord-nulldb-adapter.rb +1 -0
  32. data/lib/nulldb.rb +2 -0
  33. data/lib/nulldb/arel_compiler.rb +6 -0
  34. data/lib/nulldb/core.rb +39 -0
  35. data/lib/nulldb/extensions.rb +42 -0
  36. data/lib/nulldb/rails.rb +4 -0
  37. data/lib/nulldb_rspec.rb +104 -0
  38. data/lib/tasks/database.rake +32 -0
  39. data/nulldb.gemspec +27 -0
  40. data/spec/nulldb_spec.rb +345 -0
  41. data/spec/spec.opts +1 -0
  42. metadata +172 -0
@@ -0,0 +1,26 @@
1
+ class ActiveRecord::ConnectionAdapters::NullDBAdapter
2
+
3
+ class EmptyResult < Array
4
+ attr_writer :columns
5
+ def rows
6
+ []
7
+ end
8
+
9
+ def column_types
10
+ columns.map{|col| col.type}
11
+ end
12
+
13
+ def columns
14
+ @columns ||= []
15
+ end
16
+
17
+ def cast_values(type_overrides = nil)
18
+ rows
19
+ end
20
+
21
+ def >(num)
22
+ rows.size > num
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,5 @@
1
+ class ActiveRecord::ConnectionAdapters::NullDBAdapter
2
+
3
+ class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders); end
4
+
5
+ end
@@ -0,0 +1,13 @@
1
+ class ActiveRecord::ConnectionAdapters::NullDBAdapter
2
+
3
+ class NullObject
4
+ def method_missing(*args, &block)
5
+ nil
6
+ end
7
+
8
+ def to_a
9
+ []
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,15 @@
1
+ class ActiveRecord::ConnectionAdapters::NullDBAdapter
2
+
3
+ class Statement
4
+ attr_reader :entry_point, :content
5
+
6
+ def initialize(entry_point, content = "")
7
+ @entry_point, @content = entry_point, content
8
+ end
9
+
10
+ def ==(other)
11
+ self.entry_point == other.entry_point
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,5 @@
1
+ class ActiveRecord::ConnectionAdapters::NullDBAdapter
2
+
3
+ TableDefinition = ActiveRecord::ConnectionAdapters::TableDefinition
4
+
5
+ end
@@ -0,0 +1 @@
1
+ require 'nulldb'
@@ -0,0 +1,2 @@
1
+ require 'nulldb/core'
2
+ require 'nulldb/rails'
@@ -0,0 +1,6 @@
1
+ module Arel
2
+ module SqlCompiler
3
+ class NullDBCompiler < GenericCompiler
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,39 @@
1
+ require 'active_support'
2
+ require 'active_support/deprecation'
3
+ require 'active_record/connection_adapters/nulldb_adapter'
4
+
5
+ module NullDB
6
+ class Configuration < Struct.new(:project_root); end
7
+
8
+ class << self
9
+ def configure
10
+ @configuration = Configuration.new.tap {|c| yield c}
11
+ end
12
+
13
+ def configuration
14
+ if @configuration.nil?
15
+ raise "NullDB not configured. Require a framework, ex 'nulldb/rails'"
16
+ end
17
+
18
+ @configuration
19
+ end
20
+
21
+ def nullify(options={})
22
+ begin
23
+ @prev_connection = ActiveRecord::Base.connection_pool.try(:spec)
24
+ rescue ActiveRecord::ConnectionNotEstablished
25
+ end
26
+ ActiveRecord::Base.establish_connection(options.merge(:adapter => :nulldb))
27
+ end
28
+
29
+ def restore
30
+ if @prev_connection
31
+ ActiveRecord::Base.establish_connection(@prev_connection.config)
32
+ end
33
+ end
34
+
35
+ def checkpoint
36
+ ActiveRecord::Base.connection.checkpoint!
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,42 @@
1
+ unless respond_to?(:tap)
2
+ class Object
3
+ def tap
4
+ yield self
5
+ self
6
+ end
7
+ end
8
+ end
9
+
10
+ unless respond_to?(:try)
11
+ class Object
12
+ def try(*a, &b)
13
+ if a.empty? && block_given?
14
+ yield self
15
+ else
16
+ __send__(*a, &b)
17
+ end
18
+ end
19
+ end
20
+
21
+ class NilClass
22
+ def try(*args); nil; end
23
+ end
24
+ end
25
+
26
+ class ActiveRecord::Base
27
+ # Instantiate a new NullDB connection. Used by ActiveRecord internally.
28
+ def self.nulldb_connection(config)
29
+ ActiveRecord::ConnectionAdapters::NullDBAdapter.new(config)
30
+ end
31
+ end
32
+
33
+
34
+ module ActiveRecord
35
+ # Just make sure you have the latest version of your schema
36
+ superclass = ActiveRecord::VERSION::MAJOR == 5 ? Migration.public_send(:[], "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}".to_f) : Migration
37
+ class Schema < superclass
38
+ def self.define(info={}, &block)
39
+ instance_eval(&block)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,4 @@
1
+ require 'nulldb/core'
2
+
3
+ # Need to defer calling Rails.root because when bundler loads, Rails.root is nil
4
+ NullDB.configure {|ndb| def ndb.project_root;Rails.root;end}
@@ -0,0 +1,104 @@
1
+ require 'active_record/connection_adapters/nulldb_adapter'
2
+
3
+ module NullDB
4
+ module RSpec
5
+ end
6
+ end
7
+
8
+ module NullDB::RSpec::NullifiedDatabase
9
+ NullDBAdapter = ActiveRecord::ConnectionAdapters::NullDBAdapter
10
+
11
+ class HaveExecuted
12
+
13
+ def initialize(entry_point)
14
+ @entry_point = entry_point
15
+ end
16
+
17
+ def matches?(connection)
18
+ log = connection.execution_log_since_checkpoint
19
+ if @entry_point == :anything
20
+ not log.empty?
21
+ else
22
+ log.include?(NullDBAdapter::Statement.new(@entry_point))
23
+ end
24
+ end
25
+
26
+ def description
27
+ "connection should execute #{@entry_point} statement"
28
+ end
29
+
30
+ def failure_message
31
+ " did not execute #{@entry_point} statement when it should have"
32
+ end
33
+
34
+ def negative_failure_message
35
+ " executed #{@entry_point} statement when it should not have"
36
+ end
37
+ end
38
+
39
+ def self.globally_nullify_database
40
+ block = lambda { |config| nullify_database(config) }
41
+ if defined?(RSpec)
42
+ RSpec.configure(&block)
43
+ else
44
+ Spec::Runner.configure(&block)
45
+ end
46
+ end
47
+
48
+ def self.contextually_nullify_database(context)
49
+ nullify_database(context)
50
+ end
51
+
52
+ # A matcher for asserting that database statements have (or have not) been
53
+ # executed. Usage:
54
+ #
55
+ # ActiveRecord::Base.connection.should have_executed(:insert)
56
+ #
57
+ # The types of statement that can be matched mostly mirror the public
58
+ # operations available in
59
+ # ActiveRecord::ConnectionAdapters::DatabaseStatements:
60
+ # - :select_one
61
+ # - :select_all
62
+ # - :select_value
63
+ # - :insert
64
+ # - :update
65
+ # - :delete
66
+ # - :execute
67
+ #
68
+ # There is also a special :anything symbol that will match any operation.
69
+ def have_executed(entry_point)
70
+ HaveExecuted.new(entry_point)
71
+ end
72
+
73
+ private
74
+
75
+ def self.included(other)
76
+ if nullify_contextually?(other)
77
+ contextually_nullify_database(other)
78
+ else
79
+ globally_nullify_database
80
+ end
81
+ end
82
+
83
+ def self.nullify_contextually?(other)
84
+ if defined?(RSpec)
85
+ other < RSpec::Core::ExampleGroup
86
+ else
87
+ other.is_a? Spec::ExampleGroup
88
+ end
89
+ end
90
+
91
+ def self.nullify_database(receiver)
92
+ receiver.before :all do
93
+ ActiveRecord::Base.establish_connection(:adapter => :nulldb)
94
+ end
95
+
96
+ receiver.before :each do
97
+ ActiveRecord::Base.connection.checkpoint!
98
+ end
99
+
100
+ receiver.after :all do
101
+ ActiveRecord::Base.establish_connection(:test)
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,32 @@
1
+ # Sadly, we have to monkeypatch Rake because all of the Rails database tasks are
2
+ # hardcoded for specific adapters, with no extension points (!)
3
+ Rake::TaskManager.class_eval do
4
+ def remove_task(task_name)
5
+ @tasks.delete(task_name.to_s)
6
+ end
7
+ end
8
+
9
+ def remove_task(task_name)
10
+ Rake.application.remove_task(task_name)
11
+ end
12
+
13
+ def wrap_task(task_name, &wrapper)
14
+ wrapped_task = Rake::Task[task_name]
15
+ remove_task(Rake::Task.scope_name(Rake.application.current_scope,
16
+ task_name))
17
+ task(task_name) do
18
+ wrapper.call(wrapped_task)
19
+ end
20
+ end
21
+
22
+ namespace :db do
23
+ namespace :test do
24
+ wrap_task :purge do |wrapped_task|
25
+ if ActiveRecord::Base.configurations["test"]["adapter"] == "nulldb"
26
+ # NO-OP
27
+ else
28
+ wrapped_task.invoke
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "nulldb"
5
+ s.version = "0.3.7-alpha.1"
6
+
7
+ s.require_paths = ["lib"]
8
+ s.authors = ["Avdi Grimm", "Myron Marston"]
9
+ s.summary = "The Null Object pattern as applied to ActiveRecord database adapters"
10
+ s.description = "A database backend that translates database interactions into no-ops. Using NullDB enables you to test your model business logic - including after_save hooks - without ever touching a real database."
11
+ s.email = "myron.marston@gmail.com"
12
+ s.extra_rdoc_files = [
13
+ "LICENSE",
14
+ "README.rdoc"
15
+ ]
16
+ s.files = `git ls-files`.split($/)
17
+ s.homepage = "http://github.com/nulldb/nulldb"
18
+ s.licenses = ["MIT"]
19
+
20
+ s.add_runtime_dependency 'activerecord', '>= 2.0.0'
21
+ s.add_development_dependency 'spec'
22
+ s.add_development_dependency 'rspec'
23
+ s.add_development_dependency 'rake'
24
+ s.add_development_dependency 'appraisal'
25
+ s.add_development_dependency 'simplecov'
26
+ end
27
+
@@ -0,0 +1,345 @@
1
+ require 'rubygems'
2
+
3
+ # Optional simplecov loading
4
+ begin
5
+ require 'simplecov'
6
+ SimpleCov.start
7
+ rescue LoadError
8
+ end
9
+
10
+ require 'active_record'
11
+ require 'active_record/version'
12
+ $: << File.join(File.dirname(__FILE__), "..", "lib")
13
+
14
+ if ActiveRecord::VERSION::MAJOR > 2
15
+ require 'rspec' # rspec 2
16
+ else
17
+ require 'spec' # rspec 1
18
+ end
19
+
20
+ require 'nulldb_rspec'
21
+
22
+ class Employee < ActiveRecord::Base
23
+ after_save :on_save_finished
24
+
25
+ def on_save_finished
26
+ end
27
+ end
28
+
29
+ class TablelessModel < ActiveRecord::Base
30
+ end
31
+
32
+ NullDB.configure {|ndb| ndb.project_root = 'Rails.root'}
33
+
34
+ describe "NullDB with no schema pre-loaded" do
35
+ before :each do
36
+ allow( Kernel ).to receive :load
37
+ allow( ActiveRecord::Migration ).to receive :verbose=
38
+ end
39
+
40
+ it "should load Rails.root/db/schema.rb if no alternate is specified" do
41
+ ActiveRecord::Base.establish_connection :adapter => :nulldb
42
+ expect( Kernel ).to receive(:load).with("Rails.root/db/schema.rb")
43
+ ActiveRecord::Base.connection.columns('schema_info')
44
+ end
45
+
46
+ it "should load the specified schema relative to Rails.root" do
47
+ expect( Kernel ).to receive(:load).with("Rails.root/foo/myschema.rb")
48
+ ActiveRecord::Base.establish_connection :adapter => :nulldb,
49
+ :schema => "foo/myschema.rb"
50
+ ActiveRecord::Base.connection.columns('schema_info')
51
+ end
52
+
53
+ it "should suppress migration output" do
54
+ expect( ActiveRecord::Migration).to receive(:verbose=).with(false)
55
+ ActiveRecord::Base.establish_connection :adapter => :nulldb,
56
+ :schema => "foo/myschema.rb"
57
+ ActiveRecord::Base.connection.columns('schema_info')
58
+ end
59
+
60
+ it "should allow creating a table without passing a block" do
61
+ ActiveRecord::Base.establish_connection :adapter => :nulldb
62
+ ActiveRecord::Schema.define do
63
+ create_table(:employees)
64
+ end
65
+ end
66
+ end
67
+
68
+ describe "NullDB" do
69
+ before :all do
70
+ ActiveRecord::Base.establish_connection :adapter => :nulldb
71
+ ActiveRecord::Migration.verbose = false
72
+ ActiveRecord::Schema.define do
73
+ create_table(:employees) do |t|
74
+ t.string :name, null: false, limit: 50
75
+ t.date :hire_date
76
+ t.integer :employee_number
77
+ t.decimal :salary
78
+ end
79
+
80
+ create_table(:employees_widgets, :id => false, :force => true) do |t|
81
+ t.integer :employee_id
82
+ t.integer :widget_id
83
+ end
84
+
85
+ add_index "employees", :name, :name => "index_employees_on_name"
86
+ add_index "employees", ["employee_number"], :name => "index_employees_on_employee_number", :unique => true
87
+ add_index "employees_widgets", ["employee_id", "widget_id"], :name => "my_index"
88
+
89
+ add_fk_constraint "foo", "bar", "baz", "buz", "bungle"
90
+ add_pk_constraint "foo", "bar", {}, "baz", "buz"
91
+ end
92
+ end
93
+
94
+ before :each do
95
+ @employee = Employee.new(:name => "John Smith",
96
+ :hire_date => Date.civil(2000, 1, 1),
97
+ :employee_number => 42,
98
+ :salary => 56000.00)
99
+ end
100
+
101
+ it "should set the @config instance variable so plugins that assume its there can use it" do
102
+ expect( Employee.connection.instance_variable_get(:@config)[:adapter]).to eq :nulldb
103
+ end
104
+
105
+ it "should enable instantiation of AR objects without a database" do
106
+ expect( @employee ).to be_a_kind_of(ActiveRecord::Base)
107
+ end
108
+
109
+ it "should remember columns defined in migrations" do
110
+ should_have_column(Employee, :name, :string)
111
+ should_have_column(Employee, :hire_date, :date)
112
+ should_have_column(Employee, :employee_number, :integer)
113
+ should_have_column(Employee, :salary, :decimal)
114
+ end
115
+
116
+ it 'should have limit on name' do
117
+ expect(Employee.columns_hash['name'].limit).to eq 50
118
+ end
119
+
120
+ it "should return true on nullable field" do
121
+ expect(Employee.columns_hash['salary'].null).to be true
122
+ end
123
+
124
+ it "should return false on non-nullable field" do
125
+ expect(Employee.columns_hash['name'].null).to be false
126
+ end
127
+
128
+ it "should return the appropriate primary key" do
129
+ expect( ActiveRecord::Base.connection.primary_key('employees') ).to eq 'id'
130
+ end
131
+
132
+ it "should return a nil primary key on habtm" do
133
+ expect( ActiveRecord::Base.connection.primary_key('employees_widgets') ).to eq nil
134
+ end
135
+
136
+ it "should return an empty array of columns for a table-less model" do
137
+ expect( TablelessModel.columns).to eq []
138
+ end
139
+
140
+ it "should enable simulated saving of AR objects" do
141
+ expect{ @employee.save! }.to_not raise_error
142
+ end
143
+
144
+ it "should enable AR callbacks during simulated save" do
145
+ expect( @employee ).to receive :on_save_finished
146
+ @employee.save
147
+ end
148
+
149
+ it "should enable simulated deletes of AR objects" do
150
+ expect{ @employee.destroy }.to_not raise_error
151
+ end
152
+
153
+ it "should enable simulated creates of AR objects" do
154
+ emp = Employee.create(:name => "Bob Jones")
155
+ expect( emp.name ).to eq "Bob Jones"
156
+ end
157
+
158
+ it "should generate new IDs when inserting unsaved objects" do
159
+ cxn = Employee.connection
160
+ id1 = cxn.insert("some sql", "SomeClass Create", "id", nil, nil)
161
+ id2 = cxn.insert("some sql", "SomeClass Create", "id", nil, nil)
162
+ expect( id2 ).to eq (id1 + 1)
163
+ end
164
+
165
+ it "should re-use object ID when inserting saved objects" do
166
+ cxn = Employee.connection
167
+ id1 = cxn.insert("some sql", "SomeClass Create", "id", 23, nil)
168
+ expect( id1 ).to eq 23
169
+ end
170
+
171
+ it "should log executed SQL statements" do
172
+ cxn = Employee.connection
173
+ exec_count = cxn.execution_log.size
174
+ @employee.save!
175
+ expect( cxn.execution_log.size ).to eq (exec_count + 1)
176
+ end
177
+
178
+ it "should have the adapter name 'NullDB'" do
179
+ expect( Employee.connection.adapter_name ).to eq "NullDB"
180
+ end
181
+
182
+ it "should support migrations" do
183
+ expect( Employee.connection.supports_migrations? ).to eq true
184
+ end
185
+
186
+ it "should always have a schema_info table definition" do
187
+ expect( Employee.connection.tables ).to include "schema_info"
188
+ end
189
+
190
+ it "should return an empty array from #select" do
191
+ result = Employee.connection.select_all("who cares", "blah")
192
+ expect( result ).to eq []
193
+ end
194
+
195
+ it "should provide a way to set log checkpoints" do
196
+ cxn = Employee.connection
197
+ @employee.save!
198
+ expect( cxn.execution_log_since_checkpoint.size ).to be > 0
199
+
200
+ cxn.checkpoint!
201
+ expect( cxn.execution_log_since_checkpoint.size ).to eq 0
202
+
203
+ @employee.salary = @employee.salary + 1
204
+ @employee.save!
205
+ expect( cxn.execution_log_since_checkpoint.size ).to eq 1
206
+ end
207
+
208
+ def should_contain_statement(cxn, entry_point)
209
+ expect( cxn.execution_log_since_checkpoint).to \
210
+ include(ActiveRecord::ConnectionAdapters::NullDBAdapter::Statement.new(entry_point))
211
+ end
212
+
213
+ def should_not_contain_statement(cxn, entry_point)
214
+ expect( cxn.execution_log_since_checkpoint ).to_not \
215
+ include(ActiveRecord::ConnectionAdapters::NullDBAdapter::Statement.new(entry_point))
216
+ end
217
+
218
+ it "should tag logged statements with their entry point" do
219
+ cxn = Employee.connection
220
+
221
+ should_not_contain_statement(cxn, :insert)
222
+ @employee.save
223
+ should_contain_statement(cxn, :insert)
224
+
225
+ cxn.checkpoint!
226
+ should_not_contain_statement(cxn, :update)
227
+ @employee.salary = @employee.salary + 1
228
+ @employee.save
229
+ should_contain_statement(cxn, :update)
230
+
231
+ cxn.checkpoint!
232
+ should_not_contain_statement(cxn, :delete)
233
+ @employee.destroy
234
+ should_contain_statement(cxn, :delete)
235
+
236
+ cxn.checkpoint!
237
+ should_not_contain_statement(cxn, :select_all)
238
+ Employee.all.each do |emp|; end
239
+ should_contain_statement(cxn, :select_all)
240
+
241
+ cxn.checkpoint!
242
+ should_not_contain_statement(cxn, :select_value)
243
+ Employee.count_by_sql("frobozz")
244
+ should_contain_statement(cxn, :select_value)
245
+
246
+ cxn.checkpoint!
247
+ should_not_contain_statement(cxn, :select_values)
248
+ cxn.select_values("")
249
+ should_contain_statement(cxn, :select_values)
250
+ end
251
+
252
+ it "should allow #finish to be called on the result of #execute" do
253
+ Employee.connection.execute("blah").finish
254
+ end
255
+
256
+ it "should #to_a return empty array on the result of #execute" do
257
+ result = Employee.connection.execute("blah")
258
+ expect( result.to_a ).to be_a Array
259
+ expect( result.to_a ).to be_empty
260
+ end
261
+
262
+ def should_have_column(klass, col_name, col_type)
263
+ col = klass.columns_hash[col_name.to_s]
264
+ expect(col.sql_type.to_s.gsub(/\([0-9]+\)/, "").to_sym).to eq col_type
265
+ end
266
+
267
+
268
+ it "should support adding indexes" do
269
+ expect( Employee.connection.indexes('employees').size ).to eq 2
270
+ expect( Employee.connection.indexes('employees_widgets').size ).to eq 1
271
+ end
272
+
273
+ it "should support unique indexes" do
274
+ expect( Employee.connection.indexes('employees').detect{|idx| idx.columns == ["name"]}.unique ).to eq false
275
+ expect( Employee.connection.indexes('employees').detect{|idx| idx.columns == ["employee_number"]}.unique ).to eq true
276
+ end
277
+
278
+ it "should support multi-column indexes" do
279
+ expect( Employee.connection.indexes('employees_widgets').first.columns).to eq ["employee_id", "widget_id"]
280
+ end
281
+
282
+ it "should support custom index names" do
283
+ expect( Employee.connection.indexes('employees_widgets').first.name ).to eq 'my_index'
284
+ end
285
+
286
+ it 'should handle ActiveRecord::ConnectionNotEstablished' do
287
+ expect( ActiveRecord::Base ).to receive(:connection_pool).and_raise(ActiveRecord::ConnectionNotEstablished)
288
+ expect { NullDB.nullify }.to_not raise_error
289
+ end
290
+ end
291
+
292
+ # need a fallback db for contextual nullification
293
+ ActiveRecord::Base.configurations['test'] = {'adapter' => 'nulldb'}
294
+
295
+ describe NullDB::RSpec::NullifiedDatabase do
296
+ describe 'have_executed rspec matcher' do
297
+ before(:all) do
298
+ ActiveRecord::Schema.define do
299
+ create_table(:employees)
300
+ end
301
+ end
302
+
303
+ include NullDB::RSpec::NullifiedDatabase
304
+
305
+ before { NullDB.checkpoint }
306
+
307
+ it 'passes if an execution was made' do
308
+ expect( Employee.connection ).to receive(:insert)
309
+ allow( Kernel ).to receive :load
310
+ Employee.create
311
+ end
312
+ end
313
+
314
+ describe '.globally_nullify_database' do
315
+ it 'nullifies the database' do
316
+ expect( NullDB::RSpec::NullifiedDatabase ).to respond_to(:nullify_database)
317
+ expect( NullDB::RSpec::NullifiedDatabase ).to receive(:nullify_database)
318
+ NullDB::RSpec::NullifiedDatabase.globally_nullify_database
319
+ end
320
+ end
321
+ end
322
+
323
+
324
+ describe 'adapter-specific extensions' do
325
+ before(:all) do
326
+ ActiveRecord::Base.establish_connection :adapter => :nulldb
327
+ ActiveRecord::Migration.verbose = false
328
+ end
329
+
330
+ it "supports 'enable_extension' in the schema definition" do
331
+ expect{
332
+ ActiveRecord::Schema.define do
333
+ enable_extension "plpgsql"
334
+ end
335
+ }.to_not raise_error
336
+ end
337
+ end
338
+
339
+ describe ActiveRecord::ConnectionAdapters::NullDBAdapter::EmptyResult do
340
+ it "should return an empty array from #cast_values" do
341
+ result = described_class.new
342
+ expect( result.cast_values ).to be_a Array
343
+ expect( result.cast_values ).to be_empty
344
+ end
345
+ end