active_mocker 1.3.2 → 1.4.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|