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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/README.md +136 -24
  4. data/Rakefile +8 -2
  5. data/active_mocker.gemspec +3 -3
  6. data/lib/active_mock/association.rb +7 -0
  7. data/lib/active_mock/base.rb +250 -0
  8. data/lib/active_mock/collection.rb +52 -0
  9. data/lib/active_mock/creators.rb +25 -0
  10. data/lib/active_mock/do_nothing_active_record_methods.rb +51 -0
  11. data/lib/active_mock/has_and_belongs_to_many.rb +7 -0
  12. data/lib/active_mock/has_many.rb +54 -0
  13. data/lib/active_mock/next_id.rb +16 -0
  14. data/lib/active_mock/object_inspect.rb +39 -0
  15. data/lib/{active_mocker/collection → active_mock}/queries.rb +26 -19
  16. data/lib/active_mock/records.rb +81 -0
  17. data/lib/active_mock/relation.rb +8 -0
  18. data/lib/active_mocker.rb +3 -1
  19. data/lib/active_mocker/active_mock.rb +26 -0
  20. data/lib/active_mocker/active_record.rb +18 -0
  21. data/lib/active_mocker/active_record/relationships.rb +57 -6
  22. data/lib/active_mocker/active_record/schema.rb +1 -1
  23. data/lib/active_mocker/active_record/scope.rb +1 -1
  24. data/lib/active_mocker/active_record/unknown_class_method.rb +1 -1
  25. data/lib/active_mocker/active_record/unknown_module.rb +10 -9
  26. data/lib/active_mocker/db_to_ruby_type.rb +26 -0
  27. data/lib/active_mocker/field.rb +16 -8
  28. data/lib/active_mocker/generate.rb +19 -174
  29. data/lib/active_mocker/loaded_mocks.rb +48 -8
  30. data/lib/active_mocker/logger.rb +2 -0
  31. data/lib/active_mocker/mock_template.erb +123 -53
  32. data/lib/active_mocker/model_reader.rb +42 -13
  33. data/lib/active_mocker/model_schema.rb +279 -0
  34. data/lib/active_mocker/model_schema/generate.rb +175 -0
  35. data/lib/active_mocker/reparameterize.rb +23 -3
  36. data/lib/active_mocker/table.rb +2 -2
  37. data/lib/active_mocker/version.rb +1 -1
  38. data/sample_app_rails_4/Gemfile +1 -1
  39. data/sample_app_rails_4/app/models/micropost.rb +13 -1
  40. data/sample_app_rails_4/db/schema.rb +1 -1
  41. data/sample_app_rails_4/spec/compare_mocker_and_record_spec.rb +194 -7
  42. data/sample_app_rails_4/spec/micropost_mock_spec.rb +145 -0
  43. data/sample_app_rails_4/spec/mocks/micropost_mock.rb +81 -55
  44. data/sample_app_rails_4/spec/mocks/relationship_mock.rb +85 -54
  45. data/sample_app_rails_4/spec/mocks/user_mock.rb +71 -72
  46. data/sample_app_rails_4/spec/reload_spec.rb +1 -1
  47. data/sample_app_rails_4/spec/user_mock_spec.rb +25 -7
  48. data/spec/lib/acitve_mock/queriable_spec.rb +207 -0
  49. data/spec/lib/active_mocker/db_to_ruby_type_spec.rb +124 -0
  50. data/spec/lib/active_mocker/loaded_mocks_spec.rb +167 -0
  51. data/spec/lib/active_mocker/logger_spec.rb +32 -0
  52. data/spec/lib/active_mocker/model_reader_spec.rb +79 -28
  53. data/spec/lib/active_mocker/model_schema/generate_spec.rb +111 -0
  54. data/spec/lib/active_mocker/model_schema_spec.rb +145 -0
  55. data/spec/lib/model.rb +2 -1
  56. data/spec/lib/reparameterize_spec.rb +202 -0
  57. data/spec/unit_logger.rb +2 -2
  58. metadata +55 -35
  59. data/lib/active_hash/ar_api.rb +0 -77
  60. data/lib/active_hash/init.rb +0 -32
  61. data/lib/active_mocker/collection/association.rb +0 -12
  62. data/lib/active_mocker/collection/base.rb +0 -65
  63. data/lib/active_mocker/collection/relation.rb +0 -11
  64. data/lib/active_mocker/mock_class_methods.rb +0 -92
  65. data/lib/active_mocker/mock_instance_methods.rb +0 -84
  66. data/lib/active_mocker/mock_requires.rb +0 -10
  67. data/spec/lib/active_mocker/collection.rb +0 -94
@@ -0,0 +1,145 @@
1
+ require 'rspec'
2
+ $:.unshift File.expand_path('../../', __FILE__)
3
+ APP_ROOT = File.expand_path('../../', __FILE__) unless defined? APP_ROOT
4
+ require 'config/initializers/active_mocker.rb'
5
+ load 'spec/mocks/micropost_mock.rb'
6
+ load 'spec/mocks/user_mock.rb'
7
+
8
+ describe MicropostMock do
9
+
10
+ describe 'user=' do
11
+
12
+ it 'setting user will assign its foreign key' do
13
+ user = UserMock.create!
14
+ post = MicropostMock.create(user: user)
15
+ expect(post.user_id).to eq user.id
16
+ end
17
+
18
+ it 'setting user will not assign its foreign key if the object does not respond to persisted?' do
19
+ user = {}
20
+ post = MicropostMock.create(user: user)
21
+ expect(post.user_id).to eq nil
22
+ end
23
+
24
+ end
25
+
26
+ describe '::MAGIC_ID_NUMBER' do
27
+
28
+ it 'has constant from model' do
29
+
30
+ expect(MicropostMock::MAGIC_ID_NUMBER).to eq 90
31
+
32
+ end
33
+
34
+ end
35
+
36
+ describe '::MAGIC_ID_STRING' do
37
+
38
+ it 'has constant from model' do
39
+
40
+ expect(MicropostMock::MAGIC_ID_STRING).to eq 'F-1'
41
+
42
+ end
43
+
44
+ end
45
+
46
+ describe '::constants' do
47
+
48
+ it 'has constant from model' do
49
+
50
+ expect(MicropostMock.constants).to include(:MAGIC_ID_NUMBER, :MAGIC_ID_STRING)
51
+
52
+ end
53
+
54
+ end
55
+
56
+ describe 'Mocking methods' do
57
+
58
+ context 'mocked from class before new' do
59
+
60
+ before do
61
+ MicropostMock.mock_instance_method(:display_name) do
62
+ 'Method Mocked at class level'
63
+ end
64
+ end
65
+
66
+ it 'when no instance level mocks is set will default to class level' do
67
+ expect(MicropostMock.new.display_name).to eq 'Method Mocked at class level'
68
+ end
69
+
70
+ it 'instance mocking overrides class mocking' do
71
+ post = MicropostMock.new
72
+ post.mock_instance_method(:display_name) do
73
+ 'Method Mocked at instance level'
74
+ end
75
+ expect(post.display_name).to eq 'Method Mocked at instance level'
76
+ end
77
+
78
+ end
79
+
80
+ context 'mocked from class after new' do
81
+
82
+ before do
83
+ MicropostMock.create
84
+ MicropostMock.mock_instance_method(:display_name) do
85
+ 'Method Mocked at class level'
86
+ end
87
+
88
+ end
89
+
90
+ it 'when no instance level mocks is set will default to class level' do
91
+ expect(MicropostMock.first.display_name).to eq 'Method Mocked at class level'
92
+ end
93
+
94
+ it 'instance mocking overrides class mocking' do
95
+ post = MicropostMock.first
96
+ post.mock_instance_method(:display_name) do
97
+ 'Method Mocked at instance level'
98
+ end
99
+ expect(post.display_name).to eq 'Method Mocked at instance level'
100
+ end
101
+
102
+ end
103
+
104
+
105
+
106
+ end
107
+
108
+ describe 'Sub classing' do
109
+
110
+ context 'using sub class' do
111
+
112
+ before do
113
+ class SubUserMock < UserMock
114
+ end
115
+ end
116
+
117
+ let(:given_a_sub_user_record) { SubUserMock.create }
118
+ let(:given_a_post) { MicropostMock.create(user_id: given_a_sub_user_record.id) }
119
+
120
+ it 'when setting #user_id it will set #user from sub class' do
121
+ expect(given_a_post.user).to eq given_a_sub_user_record
122
+ expect(given_a_post.user.class).to eq SubUserMock
123
+ end
124
+
125
+ end
126
+
127
+ context 'without a sub class' do
128
+
129
+ let(:given_a_sub_user_record) { UserMock.create }
130
+ let(:given_a_post) { MicropostMock.create(user_id: given_a_sub_user_record.id) }
131
+
132
+ it 'when setting #user_id it will set #user from sub class' do
133
+ expect(given_a_post.user).to eq given_a_sub_user_record
134
+ expect(given_a_post.user.class).to eq UserMock
135
+ end
136
+
137
+ end
138
+
139
+ end
140
+
141
+ after(:each) do
142
+ ActiveMocker::LoadedMocks.clear_all
143
+ end
144
+
145
+ end
@@ -1,24 +1,50 @@
1
- require 'active_mocker/mock_requires'
2
- Object.send(:remove_const, "MicropostMock") if ActiveMocker.class_exists?("MicropostMock")
1
+ require 'active_mocker/active_mock'
2
+ Object.send(:remove_const, "MicropostMock") if Object.const_defined?("MicropostMock")
3
3
 
4
- class MicropostMock < ::ActiveHash::Base
5
- include ActiveMocker::ActiveHash::ARApi
6
- include ActiveMocker::MockInstanceMethods
7
- extend ActiveMocker::MockClassMethods
4
+ class MicropostMock < ActiveMock::Base
8
5
 
9
- def initialize(attributes={}, &block)
10
- @attributes = HashWithIndifferentAccess.new({"id"=>nil, "content"=>nil, "user_id"=>nil, "up_votes"=>nil, "created_at"=>nil, "updated_at"=>nil})
11
- @associations = HashWithIndifferentAccess.new({:user=>nil})
12
- super(attributes, &block)
13
- end
6
+ MAGIC_ID_NUMBER = 90
14
7
 
8
+ MAGIC_ID_STRING = "F-1"
15
9
 
16
- def self.column_names
17
- ["id", "content", "user_id", "up_votes", "created_at", "updated_at"]
18
- end
10
+ class << self
11
+
12
+ def attributes
13
+ @attributes ||= HashWithIndifferentAccess.new({"id"=>nil, "content"=>nil, "user_id"=>nil, "up_votes"=>nil, "created_at"=>nil, "updated_at"=>nil})
14
+ end
15
+
16
+ def types
17
+ @types ||= { id: build_type(Fixnum), content: build_type(String), user_id: build_type(Fixnum), up_votes: build_type(Fixnum), created_at: build_type(DateTime), updated_at: build_type(DateTime) }
18
+ end
19
+
20
+ def associations
21
+ @associations ||= {:user=>nil}
22
+ end
23
+
24
+ def model_instance_methods
25
+ @model_instance_methods ||= {"display_name"=>:not_implemented}
26
+ end
27
+
28
+ def model_class_methods
29
+ @model_class_methods ||= {"from_users_followed_by"=>:not_implemented}
30
+ end
31
+
32
+ def mocked_class
33
+ 'Micropost'
34
+ end
35
+
36
+ def column_names
37
+ attribute_names
38
+ end
39
+
40
+ def attribute_names
41
+ @attribute_names ||= ["id", "content", "user_id", "up_votes", "created_at", "updated_at"]
42
+ end
43
+
44
+ def primary_key
45
+ "id"
46
+ end
19
47
 
20
- def self.attribute_names
21
- @attribute_names = ["id", "content", "user_id", "up_votes", "created_at", "updated_at"]
22
48
  end
23
49
 
24
50
  ##################################
@@ -26,102 +52,102 @@ class MicropostMock < ::ActiveHash::Base
26
52
  ##################################
27
53
 
28
54
  def id
29
- @attributes['id']
55
+ read_attribute(:id)
30
56
  end
31
57
 
32
58
  def id=(val)
33
- type = (types[:id] ||= Virtus::Attribute.build(Fixnum))
34
- @attributes['id'] = type.coerce(val)
59
+ write_attribute(:id, val)
35
60
  end
36
61
 
37
62
  def content
38
- @attributes['content']
63
+ read_attribute(:content)
39
64
  end
40
65
 
41
66
  def content=(val)
42
- type = (types[:content] ||= Virtus::Attribute.build(String))
43
- @attributes['content'] = type.coerce(val)
67
+ write_attribute(:content, val)
44
68
  end
45
69
 
46
70
  def user_id
47
- @attributes['user_id']
71
+ read_attribute(:user_id)
48
72
  end
49
73
 
50
74
  def user_id=(val)
51
- type = (types[:user_id] ||= Virtus::Attribute.build(Fixnum))
52
- @attributes['user_id'] = type.coerce(val)
75
+ write_attribute(:user_id, val)
76
+ association = classes('User').try(:find, user_id)
77
+ write_association(:user,association) unless association.nil?
53
78
  end
54
79
 
55
80
  def up_votes
56
- @attributes['up_votes']
81
+ read_attribute(:up_votes)
57
82
  end
58
83
 
59
84
  def up_votes=(val)
60
- type = (types[:up_votes] ||= Virtus::Attribute.build(Fixnum))
61
- @attributes['up_votes'] = type.coerce(val)
85
+ write_attribute(:up_votes, val)
62
86
  end
63
87
 
64
88
  def created_at
65
- @attributes['created_at']
89
+ read_attribute(:created_at)
66
90
  end
67
91
 
68
92
  def created_at=(val)
69
- type = (types[:created_at] ||= Virtus::Attribute.build(DateTime))
70
- @attributes['created_at'] = type.coerce(val)
93
+ write_attribute(:created_at, val)
71
94
  end
72
95
 
73
96
  def updated_at
74
- @attributes['updated_at']
97
+ read_attribute(:updated_at)
75
98
  end
76
99
 
77
100
  def updated_at=(val)
78
- type = (types[:updated_at] ||= Virtus::Attribute.build(DateTime))
79
- @attributes['updated_at'] = type.coerce(val)
101
+ write_attribute(:updated_at, val)
80
102
  end
81
103
 
82
104
  ##################################
83
- # Association getter/setters #
105
+ # Associations #
84
106
  ##################################
85
107
 
86
- def self.association_names
87
- @association_names = [:user]
88
- end
89
-
108
+ # belongs_to
90
109
  def user
91
- associations['user']
110
+ @associations[:user]
92
111
  end
93
112
 
94
113
  def user=(val)
95
- associations['user'] = val
114
+ @associations[:user] = val
115
+ write_attribute(:user_id, val.id) if val.respond_to?(:persisted?) && val.persisted?
116
+ end
117
+
118
+ def build_user(attributes={}, &block)
119
+ association = classes('User').try(:new, attributes, &block)
120
+ write_association(:user, association) unless association.nil?
96
121
  end
97
122
 
123
+ def create_user(attributes={}, &block)
124
+ association = classes('User').try(:create,attributes, &block)
125
+ write_association(:user, nil) unless association.nil?
126
+ end
127
+ alias_method :create_user!, :create_user
128
+
129
+
98
130
  ##################################
99
131
  # Model Methods getter/setters #
100
132
  ##################################
101
133
 
102
- def self.model_instance_methods
103
- @model_instance_methods ||= {}
104
- end
105
-
106
- def self.model_class_methods
107
- @model_class_methods ||= {"from_users_followed_by"=>:not_implemented}
108
- end
109
134
 
110
- def self.clear_mock
111
- @model_class_methods, @model_instance_methods = nil, nil
112
- delete_all
135
+ def display_name()
136
+ block = model_instance_methods['display_name']
137
+ self.class.is_implemented(block, '#display_name')
138
+ instance_exec(*[], &block)
113
139
  end
114
140
 
115
- def self.from_users_followed_by(user)
141
+ def self.from_users_followed_by(user=nil)
116
142
  block = model_class_methods['from_users_followed_by']
117
143
  is_implemented(block, '::from_users_followed_by')
118
144
  instance_exec(*[user], &block)
119
145
  end
120
146
 
147
+ private
148
+
121
149
  def self.reload
122
150
  load __FILE__
123
151
  end
124
152
 
125
- end
126
-
127
- ActiveMocker::LoadedMocks.add(MicropostMock)
153
+ end
@@ -1,24 +1,46 @@
1
- require 'active_mocker/mock_requires'
2
- Object.send(:remove_const, "RelationshipMock") if ActiveMocker.class_exists?("RelationshipMock")
1
+ require 'active_mocker/active_mock'
2
+ Object.send(:remove_const, "RelationshipMock") if Object.const_defined?("RelationshipMock")
3
3
 
4
- class RelationshipMock < ::ActiveHash::Base
5
- include ActiveMocker::ActiveHash::ARApi
6
- include ActiveMocker::MockInstanceMethods
7
- extend ActiveMocker::MockClassMethods
4
+ class RelationshipMock < ActiveMock::Base
8
5
 
9
- def initialize(attributes={}, &block)
10
- @attributes = HashWithIndifferentAccess.new({"id"=>nil, "follower_id"=>nil, "followed_id"=>nil, "created_at"=>nil, "updated_at"=>nil})
11
- @associations = HashWithIndifferentAccess.new({:follower=>nil, :followed=>nil})
12
- super(attributes, &block)
13
- end
6
+ class << self
14
7
 
8
+ def attributes
9
+ @attributes ||= HashWithIndifferentAccess.new({"id"=>nil, "follower_id"=>nil, "followed_id"=>nil, "created_at"=>nil, "updated_at"=>nil})
10
+ end
15
11
 
16
- def self.column_names
17
- ["id", "follower_id", "followed_id", "created_at", "updated_at"]
18
- end
12
+ def types
13
+ @types ||= { id: build_type(Fixnum), follower_id: build_type(Fixnum), followed_id: build_type(Fixnum), created_at: build_type(DateTime), updated_at: build_type(DateTime) }
14
+ end
15
+
16
+ def associations
17
+ @associations ||= {:follower=>nil, :followed=>nil}
18
+ end
19
+
20
+ def model_instance_methods
21
+ @model_instance_methods ||= {}
22
+ end
23
+
24
+ def model_class_methods
25
+ @model_class_methods ||= {}
26
+ end
27
+
28
+ def mocked_class
29
+ 'Relationship'
30
+ end
31
+
32
+ def column_names
33
+ attribute_names
34
+ end
35
+
36
+ def attribute_names
37
+ @attribute_names ||= ["id", "follower_id", "followed_id", "created_at", "updated_at"]
38
+ end
39
+
40
+ def primary_key
41
+ "id"
42
+ end
19
43
 
20
- def self.attribute_names
21
- @attribute_names = ["id", "follower_id", "followed_id", "created_at", "updated_at"]
22
44
  end
23
45
 
24
46
  ##################################
@@ -26,95 +48,104 @@ class RelationshipMock < ::ActiveHash::Base
26
48
  ##################################
27
49
 
28
50
  def id
29
- @attributes['id']
51
+ read_attribute(:id)
30
52
  end
31
53
 
32
54
  def id=(val)
33
- type = (types[:id] ||= Virtus::Attribute.build(Fixnum))
34
- @attributes['id'] = type.coerce(val)
55
+ write_attribute(:id, val)
35
56
  end
36
57
 
37
58
  def follower_id
38
- @attributes['follower_id']
59
+ read_attribute(:follower_id)
39
60
  end
40
61
 
41
62
  def follower_id=(val)
42
- type = (types[:follower_id] ||= Virtus::Attribute.build(Fixnum))
43
- @attributes['follower_id'] = type.coerce(val)
63
+ write_attribute(:follower_id, val)
64
+ association = classes('User').try(:find, follower_id)
65
+ write_association(:follower,association) unless association.nil?
44
66
  end
45
67
 
46
68
  def followed_id
47
- @attributes['followed_id']
69
+ read_attribute(:followed_id)
48
70
  end
49
71
 
50
72
  def followed_id=(val)
51
- type = (types[:followed_id] ||= Virtus::Attribute.build(Fixnum))
52
- @attributes['followed_id'] = type.coerce(val)
73
+ write_attribute(:followed_id, val)
74
+ association = classes('User').try(:find, followed_id)
75
+ write_association(:followed,association) unless association.nil?
53
76
  end
54
77
 
55
78
  def created_at
56
- @attributes['created_at']
79
+ read_attribute(:created_at)
57
80
  end
58
81
 
59
82
  def created_at=(val)
60
- type = (types[:created_at] ||= Virtus::Attribute.build(DateTime))
61
- @attributes['created_at'] = type.coerce(val)
83
+ write_attribute(:created_at, val)
62
84
  end
63
85
 
64
86
  def updated_at
65
- @attributes['updated_at']
87
+ read_attribute(:updated_at)
66
88
  end
67
89
 
68
90
  def updated_at=(val)
69
- type = (types[:updated_at] ||= Virtus::Attribute.build(DateTime))
70
- @attributes['updated_at'] = type.coerce(val)
91
+ write_attribute(:updated_at, val)
71
92
  end
72
93
 
73
94
  ##################################
74
- # Association getter/setters #
95
+ # Associations #
75
96
  ##################################
76
97
 
77
- def self.association_names
78
- @association_names = [:follower, :followed]
79
- end
80
-
98
+ # belongs_to
81
99
  def follower
82
- associations['follower']
100
+ @associations[:follower]
83
101
  end
84
102
 
85
103
  def follower=(val)
86
- associations['follower'] = val
104
+ @associations[:follower] = val
105
+ write_attribute(:follower_id, val.id) if val.respond_to?(:persisted?) && val.persisted?
106
+ end
107
+
108
+ def build_follower(attributes={}, &block)
109
+ association = classes('User').try(:new, attributes, &block)
110
+ write_association(:follower, association) unless association.nil?
87
111
  end
88
112
 
113
+ def create_follower(attributes={}, &block)
114
+ association = classes('User').try(:create,attributes, &block)
115
+ write_association(:follower, nil) unless association.nil?
116
+ end
117
+ alias_method :create_follower!, :create_follower
118
+
89
119
  def followed
90
- associations['followed']
120
+ @associations[:followed]
91
121
  end
92
122
 
93
123
  def followed=(val)
94
- associations['followed'] = val
124
+ @associations[:followed] = val
125
+ write_attribute(:followed_id, val.id) if val.respond_to?(:persisted?) && val.persisted?
126
+ end
127
+
128
+ def build_followed(attributes={}, &block)
129
+ association = classes('User').try(:new, attributes, &block)
130
+ write_association(:followed, association) unless association.nil?
131
+ end
132
+
133
+ def create_followed(attributes={}, &block)
134
+ association = classes('User').try(:create,attributes, &block)
135
+ write_association(:followed, nil) unless association.nil?
95
136
  end
137
+ alias_method :create_followed!, :create_followed
138
+
96
139
 
97
140
  ##################################
98
141
  # Model Methods getter/setters #
99
142
  ##################################
100
143
 
101
- def self.model_instance_methods
102
- @model_instance_methods ||= {}
103
- end
104
-
105
- def self.model_class_methods
106
- @model_class_methods ||= {}
107
- end
108
144
 
109
- def self.clear_mock
110
- @model_class_methods, @model_instance_methods = nil, nil
111
- delete_all
112
- end
145
+ private
113
146
 
114
147
  def self.reload
115
148
  load __FILE__
116
149
  end
117
150
 
118
- end
119
-
120
- ActiveMocker::LoadedMocks.add(RelationshipMock)
151
+ end