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.
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