active_mocker 1.3.2 → 1.4.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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/README.md +136 -24
- data/Rakefile +8 -2
- data/active_mocker.gemspec +3 -3
- data/lib/active_mock/association.rb +7 -0
- data/lib/active_mock/base.rb +250 -0
- data/lib/active_mock/collection.rb +52 -0
- data/lib/active_mock/creators.rb +25 -0
- data/lib/active_mock/do_nothing_active_record_methods.rb +51 -0
- data/lib/active_mock/has_and_belongs_to_many.rb +7 -0
- data/lib/active_mock/has_many.rb +54 -0
- data/lib/active_mock/next_id.rb +16 -0
- data/lib/active_mock/object_inspect.rb +39 -0
- data/lib/{active_mocker/collection → active_mock}/queries.rb +26 -19
- data/lib/active_mock/records.rb +81 -0
- data/lib/active_mock/relation.rb +8 -0
- data/lib/active_mocker.rb +3 -1
- data/lib/active_mocker/active_mock.rb +26 -0
- data/lib/active_mocker/active_record.rb +18 -0
- data/lib/active_mocker/active_record/relationships.rb +57 -6
- data/lib/active_mocker/active_record/schema.rb +1 -1
- data/lib/active_mocker/active_record/scope.rb +1 -1
- data/lib/active_mocker/active_record/unknown_class_method.rb +1 -1
- data/lib/active_mocker/active_record/unknown_module.rb +10 -9
- data/lib/active_mocker/db_to_ruby_type.rb +26 -0
- data/lib/active_mocker/field.rb +16 -8
- data/lib/active_mocker/generate.rb +19 -174
- data/lib/active_mocker/loaded_mocks.rb +48 -8
- data/lib/active_mocker/logger.rb +2 -0
- data/lib/active_mocker/mock_template.erb +123 -53
- data/lib/active_mocker/model_reader.rb +42 -13
- data/lib/active_mocker/model_schema.rb +279 -0
- data/lib/active_mocker/model_schema/generate.rb +175 -0
- data/lib/active_mocker/reparameterize.rb +23 -3
- data/lib/active_mocker/table.rb +2 -2
- data/lib/active_mocker/version.rb +1 -1
- data/sample_app_rails_4/Gemfile +1 -1
- data/sample_app_rails_4/app/models/micropost.rb +13 -1
- data/sample_app_rails_4/db/schema.rb +1 -1
- data/sample_app_rails_4/spec/compare_mocker_and_record_spec.rb +194 -7
- data/sample_app_rails_4/spec/micropost_mock_spec.rb +145 -0
- data/sample_app_rails_4/spec/mocks/micropost_mock.rb +81 -55
- data/sample_app_rails_4/spec/mocks/relationship_mock.rb +85 -54
- data/sample_app_rails_4/spec/mocks/user_mock.rb +71 -72
- data/sample_app_rails_4/spec/reload_spec.rb +1 -1
- data/sample_app_rails_4/spec/user_mock_spec.rb +25 -7
- data/spec/lib/acitve_mock/queriable_spec.rb +207 -0
- data/spec/lib/active_mocker/db_to_ruby_type_spec.rb +124 -0
- data/spec/lib/active_mocker/loaded_mocks_spec.rb +167 -0
- data/spec/lib/active_mocker/logger_spec.rb +32 -0
- data/spec/lib/active_mocker/model_reader_spec.rb +79 -28
- data/spec/lib/active_mocker/model_schema/generate_spec.rb +111 -0
- data/spec/lib/active_mocker/model_schema_spec.rb +145 -0
- data/spec/lib/model.rb +2 -1
- data/spec/lib/reparameterize_spec.rb +202 -0
- data/spec/unit_logger.rb +2 -2
- metadata +55 -35
- data/lib/active_hash/ar_api.rb +0 -77
- data/lib/active_hash/init.rb +0 -32
- data/lib/active_mocker/collection/association.rb +0 -12
- data/lib/active_mocker/collection/base.rb +0 -65
- data/lib/active_mocker/collection/relation.rb +0 -11
- data/lib/active_mocker/mock_class_methods.rb +0 -92
- data/lib/active_mocker/mock_instance_methods.rb +0 -84
- data/lib/active_mocker/mock_requires.rb +0 -10
- data/spec/lib/active_mocker/collection.rb +0 -94
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'rspec/given'
|
3
|
+
$:.unshift File.expand_path('../../../lib', __FILE__)
|
4
|
+
require 'bigdecimal'
|
5
|
+
require 'axiom/types'
|
6
|
+
require 'active_mocker/db_to_ruby_type'
|
7
|
+
|
8
|
+
describe ActiveMocker::DBToRubyType do
|
9
|
+
|
10
|
+
describe '::call' do
|
11
|
+
|
12
|
+
context 'integer' do
|
13
|
+
|
14
|
+
Given(:db_type) { :integer }
|
15
|
+
|
16
|
+
When (:call) { described_class.call(db_type) }
|
17
|
+
|
18
|
+
Then { expect(call).to eq(Fixnum) }
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'float' do
|
23
|
+
|
24
|
+
Given(:db_type) { :float }
|
25
|
+
|
26
|
+
When (:call) { described_class.call(db_type) }
|
27
|
+
|
28
|
+
Then { expect(call).to eq(Float) }
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'decimal' do
|
33
|
+
|
34
|
+
Given(:db_type) { :decimal }
|
35
|
+
|
36
|
+
When (:call) { described_class.call(db_type) }
|
37
|
+
|
38
|
+
Then { expect(call).to eq(BigDecimal) }
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'timestamp' do
|
43
|
+
|
44
|
+
Given(:db_type) { :timestamp }
|
45
|
+
|
46
|
+
When (:call) { described_class.call(db_type) }
|
47
|
+
|
48
|
+
Then { expect(call).to eq(Time) }
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'time' do
|
53
|
+
|
54
|
+
Given(:db_type) { :time }
|
55
|
+
|
56
|
+
When (:call) { described_class.call(db_type) }
|
57
|
+
|
58
|
+
Then { expect(call).to eq(Time) }
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'datetime' do
|
63
|
+
|
64
|
+
Given(:db_type) { :datetime }
|
65
|
+
|
66
|
+
When (:call) { described_class.call(db_type) }
|
67
|
+
|
68
|
+
Then { expect(call).to eq(DateTime) }
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'date' do
|
73
|
+
|
74
|
+
Given(:db_type) { :date }
|
75
|
+
|
76
|
+
When (:call) { described_class.call(db_type) }
|
77
|
+
|
78
|
+
Then { expect(call).to eq(Date) }
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'text' do
|
83
|
+
|
84
|
+
Given(:db_type) { :text }
|
85
|
+
|
86
|
+
When (:call) { described_class.call(db_type) }
|
87
|
+
|
88
|
+
Then { expect(call).to eq(String) }
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'string' do
|
93
|
+
|
94
|
+
Given(:db_type) { :string }
|
95
|
+
|
96
|
+
When (:call) { described_class.call(db_type) }
|
97
|
+
|
98
|
+
Then { expect(call).to eq(String) }
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'binary' do
|
103
|
+
|
104
|
+
Given(:db_type) { :binary }
|
105
|
+
|
106
|
+
When (:call) { described_class.call(db_type) }
|
107
|
+
|
108
|
+
Then { expect(call).to eq(String) }
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'boolean' do
|
113
|
+
|
114
|
+
Given(:db_type) { :boolean }
|
115
|
+
|
116
|
+
When (:call) { described_class.call(db_type) }
|
117
|
+
|
118
|
+
Then { expect(call).to eq(Axiom::Types::Boolean) }
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
$:.unshift File.expand_path('../../', __FILE__)
|
3
|
+
require 'active_mocker/loaded_mocks'
|
4
|
+
|
5
|
+
describe ActiveMocker::LoadedMocks do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
|
9
|
+
class MockClass
|
10
|
+
def self.mocked_class
|
11
|
+
@@clear_called = false
|
12
|
+
@@delete_all_called = false
|
13
|
+
@@reload_all_called = false
|
14
|
+
'Object'
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.clear_mock
|
18
|
+
@@clear_called = true
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.delete_all
|
22
|
+
@@delete_all_called = true
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.reload
|
26
|
+
@@reload_all_called = true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class MockClass2
|
31
|
+
def self.mocked_class
|
32
|
+
@@clear_called = false
|
33
|
+
@@delete_all_called = false
|
34
|
+
@@reload_all_called = false
|
35
|
+
'Object'
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.clear_mock
|
39
|
+
@@clear_called = true
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.delete_all
|
43
|
+
@@delete_all_called = true
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.reload
|
47
|
+
@@reload_all_called = true
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
after(:each) do
|
54
|
+
described_class.send(:internal_clear)
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '::class_name_to_mock' do
|
58
|
+
|
59
|
+
subject{ described_class.class_name_to_mock }
|
60
|
+
|
61
|
+
it 'returns key of mocked_class and a constant of the mock class' do
|
62
|
+
described_class.add MockClass
|
63
|
+
expect(subject).to eq({'Object' => MockClass})
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '::clear_all' do
|
69
|
+
|
70
|
+
before do
|
71
|
+
ActiveMocker::LoadedMocks.add MockClass
|
72
|
+
ActiveMocker::LoadedMocks.add_subclass MockClass2
|
73
|
+
described_class.clear_all
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'will call clear_mock on each loaded mock' do
|
77
|
+
expect(clear_mock_called?(MockClass)).to eq true
|
78
|
+
expect(clear_mock_called?(MockClass2)).to eq true
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'will empty the sub classes' do
|
82
|
+
expect(ActiveMocker::LoadedMocks.subclasses.empty?).to eq true
|
83
|
+
end
|
84
|
+
|
85
|
+
def clear_mock_called?(mock)
|
86
|
+
return true if mock.class_variable_get(:@@clear_called)
|
87
|
+
return false
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '::delete_all' do
|
93
|
+
|
94
|
+
it 'will call delete_all on each loaded mock' do
|
95
|
+
|
96
|
+
described_class.add MockClass
|
97
|
+
described_class.add_subclass MockClass2
|
98
|
+
described_class.delete_all
|
99
|
+
expect(delete_all_called?(MockClass)).to eq true
|
100
|
+
expect(delete_all_called?(MockClass2)).to eq true
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
def delete_all_called?(mock)
|
105
|
+
return true if mock.class_variable_get(:@@delete_all_called)
|
106
|
+
return false
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
describe '::mocks' do
|
112
|
+
|
113
|
+
it 'returns hash the key being a string and the value being the constant' do
|
114
|
+
|
115
|
+
described_class.add MockClass
|
116
|
+
described_class.add MockClass2
|
117
|
+
expect(described_class.mocks).to eq({"MockClass" => MockClass, "MockClass2" => MockClass2})
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
describe '::all' do
|
124
|
+
|
125
|
+
it 'returns hash the key being a string and the value being the constant' do
|
126
|
+
|
127
|
+
described_class.add MockClass
|
128
|
+
described_class.add MockClass2
|
129
|
+
expect(described_class.all).to eq({"MockClass" => MockClass, "MockClass2" => MockClass2})
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '::undefine_all' do
|
136
|
+
|
137
|
+
# it 'will call delete_all on each loaded mock' do
|
138
|
+
#
|
139
|
+
# described_class.add MockClass
|
140
|
+
# described_class.add MockClass2
|
141
|
+
#
|
142
|
+
# described_class.undefine_all
|
143
|
+
# expect(Object.const_defined?('MockClass')).to eq false
|
144
|
+
# expect(Object.const_defined?('MockClass2')).to eq false
|
145
|
+
#
|
146
|
+
# end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
describe '::reload_all' do
|
151
|
+
|
152
|
+
it 'will call reload on each loaded mock' do
|
153
|
+
described_class.add MockClass
|
154
|
+
described_class.add_subclass MockClass2
|
155
|
+
described_class.reload_all
|
156
|
+
expect(reload_all_called?(MockClass)).to eq true
|
157
|
+
expect(reload_all_called?(MockClass2)).to eq true
|
158
|
+
end
|
159
|
+
|
160
|
+
def reload_all_called?(mock)
|
161
|
+
return true if mock.class_variable_get(:@@reload_all_called)
|
162
|
+
return false
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
$:.unshift File.expand_path('../../', __FILE__)
|
3
|
+
require 'active_mocker/logger'
|
4
|
+
|
5
|
+
describe ActiveMocker::Logger do
|
6
|
+
|
7
|
+
describe '::set' do
|
8
|
+
|
9
|
+
let(:logger){double()}
|
10
|
+
|
11
|
+
around do
|
12
|
+
described_class.class_variable_set(:@@logger, nil)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'set the logger to be used by the mock class' do
|
16
|
+
described_class.set(logger)
|
17
|
+
expect(described_class.class_variable_get(:@@logger)).to eq(logger)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'will pass any methods to the set logger' do
|
21
|
+
described_class.set(logger)
|
22
|
+
expect(logger).to receive(:info)
|
23
|
+
described_class.info
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'will return nil if no logger is set' do
|
27
|
+
expect(described_class.any_method).to eq nil
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rspec'
|
2
2
|
$:.unshift File.expand_path('../../', __FILE__)
|
3
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
3
4
|
require 'singleton'
|
4
5
|
require 'logger'
|
5
6
|
require 'active_mocker/logger'
|
@@ -17,7 +18,9 @@ describe ActiveMocker::ModelReader do
|
|
17
18
|
ActiveMocker::Logger.set(UnitLogger)
|
18
19
|
end
|
19
20
|
|
20
|
-
let(:
|
21
|
+
let(:model_reader){ described_class.new({model_dir: File.expand_path('../../', __FILE__)}).parse('model') }
|
22
|
+
|
23
|
+
let(:subject){ model_reader}
|
21
24
|
|
22
25
|
describe '#parse' do
|
23
26
|
|
@@ -61,64 +64,112 @@ describe ActiveMocker::ModelReader do
|
|
61
64
|
|
62
65
|
end
|
63
66
|
|
64
|
-
describe '#
|
65
|
-
|
66
|
-
it '#belongs_to' do
|
67
|
+
describe '#belongs_to' do
|
67
68
|
|
68
|
-
|
69
|
+
let(:subject){model_reader.belongs_to}
|
69
70
|
|
71
|
+
it 'name of association' do
|
72
|
+
expect(subject.first.name).to eq(:company)
|
70
73
|
end
|
71
74
|
|
72
|
-
it '
|
73
|
-
|
74
|
-
expect(subject.relationships_types.has_many).to eq([[:users]])
|
75
|
-
|
75
|
+
it 'class_name override' do
|
76
|
+
expect(subject.first.class_name).to eq('PlanServiceCategory')
|
76
77
|
end
|
77
78
|
|
78
|
-
it '
|
79
|
-
|
80
|
-
expect(subject.relationships_types.has_one).to eq([[:account]])
|
81
|
-
|
79
|
+
it 'infer class_name' do
|
80
|
+
expect(subject.last.class_name).to eq('Person')
|
82
81
|
end
|
83
82
|
|
84
|
-
it '
|
83
|
+
it 'infer foreign key' do
|
84
|
+
expect(subject.last.foreign_key).to eq('person_id')
|
85
|
+
end
|
85
86
|
|
86
|
-
|
87
|
+
it 'foreign key override' do
|
88
|
+
expect(subject.first.foreign_key).to eq('category_id')
|
89
|
+
end
|
87
90
|
|
91
|
+
it 'through' do
|
92
|
+
expect(subject.last.through).to eq('customer')
|
88
93
|
end
|
89
94
|
|
90
95
|
end
|
91
96
|
|
92
|
-
describe '#
|
93
|
-
|
94
|
-
it 'returns an array of relations' do
|
97
|
+
describe '#has_one' do
|
95
98
|
|
96
|
-
|
99
|
+
let(:subject) { model_reader.has_one }
|
97
100
|
|
101
|
+
it 'name of association' do
|
102
|
+
expect(subject.first.name).to eq(:account)
|
98
103
|
end
|
99
104
|
|
100
105
|
end
|
101
106
|
|
102
|
-
describe '#
|
103
|
-
|
104
|
-
it 'returns an array of relations' do
|
107
|
+
describe '#has_many' do
|
105
108
|
|
106
|
-
|
109
|
+
let(:subject) { model_reader.has_many }
|
107
110
|
|
111
|
+
it 'name of association' do
|
112
|
+
expect(subject.first.name).to eq(:users)
|
108
113
|
end
|
109
114
|
|
110
115
|
end
|
111
116
|
|
112
|
-
describe '#
|
117
|
+
describe '#has_and_belongs_to_many' do
|
113
118
|
|
114
|
-
|
115
|
-
|
116
|
-
expect(subject.single_relationships).to eq [:company, :account]
|
119
|
+
let(:subject) { model_reader.has_and_belongs_to_many }
|
117
120
|
|
121
|
+
it 'name of association' do
|
122
|
+
expect(subject.first.name).to eq(:disclosures)
|
118
123
|
end
|
119
124
|
|
120
125
|
end
|
121
126
|
|
127
|
+
# TODO JoinTable
|
128
|
+
# class Assembly < ActiveRecord::Base
|
129
|
+
# has_and_belongs_to_many :parts
|
130
|
+
# end
|
131
|
+
#
|
132
|
+
# class Part < ActiveRecord::Base
|
133
|
+
# has_and_belongs_to_many :assemblies
|
134
|
+
# end
|
135
|
+
# These need to be backed up by a migration to create the assemblies_parts table.This table should be created without a primary key:
|
136
|
+
|
137
|
+
# class CreateAssembliesPartsJoinTable < ActiveRecord::Migration
|
138
|
+
# def change
|
139
|
+
# create_table :assemblies_parts, id: false do |t|
|
140
|
+
# t.integer :assembly_id
|
141
|
+
# t.integer :part_id
|
142
|
+
# end
|
143
|
+
# end
|
144
|
+
# end
|
145
|
+
|
146
|
+
# TODO Polymorphic Associations
|
147
|
+
# A slightly more advanced twist on associations is the polymorphic association.With polymorphic associations, a model can belong to more than one other model, on a single association.For example, you might have a picture model that belongs to either an employee model or a product model.Here 's how this could be declared:
|
148
|
+
#
|
149
|
+
# class Picture < ActiveRecord::Base
|
150
|
+
# belongs_to :imageable, polymorphic: true
|
151
|
+
# end
|
152
|
+
#
|
153
|
+
# class Employee < ActiveRecord::Base
|
154
|
+
# has_many :pictures, as: :imageable
|
155
|
+
# end
|
156
|
+
#
|
157
|
+
# class Product < ActiveRecord::Base
|
158
|
+
# has_many :pictures, as: :imageable
|
159
|
+
# end
|
160
|
+
|
161
|
+
# class CreatePictures < ActiveRecord::Migration
|
162
|
+
# def change
|
163
|
+
# create_table :pictures do |t|
|
164
|
+
# t.string :name
|
165
|
+
# t.integer :imageable_id
|
166
|
+
# t.string :imageable_type
|
167
|
+
# t.timestamps
|
168
|
+
# end
|
169
|
+
# end
|
170
|
+
# end
|
171
|
+
|
172
|
+
|
122
173
|
|
123
174
|
context 'inject string_reader as file_reader' do
|
124
175
|
|
@@ -143,7 +194,7 @@ describe ActiveMocker::ModelReader do
|
|
143
194
|
let(:search){subject.parse('person')}
|
144
195
|
|
145
196
|
it 'let not read a file but return a string instead to be evaluated' do
|
146
|
-
expect(search.relationships_types.belongs_to).to eq
|
197
|
+
expect(search.relationships_types.belongs_to.first.name).to eq :zip_code
|
147
198
|
expect(subject.instance_methods).to eq([:full_name])
|
148
199
|
expect(subject.instance_methods_with_arguments).to eq([{:full_name=>[[:req, :first_name], [:req, :last_name]]}])
|
149
200
|
end
|