active_mocker 2.5.1 → 2.5.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 785f7ca8b4d2444dfd83cb8352f76590228b6f75
4
- data.tar.gz: 90ca606083940692eaa6775f0628320028bde325
3
+ metadata.gz: 5e2c739418bd430963f4bd13337a9ede2fad3530
4
+ data.tar.gz: 8a5a7d90e9a7c1169a8738c8df531d85b841f411
5
5
  SHA512:
6
- metadata.gz: a8aaaa9f3670f62b90e3f8ea0b9e7a0448b713c7d12187ed7bf69eb52ef2d5d9e266092a38bccd6e810fb30d25837154f083c80453ffed6d01a4e008b649696d
7
- data.tar.gz: 94726fc0af740ead662ab8965ab8f47300c000980c0ef16cc0643b52a9e49f2bcb20e4cd4da2e0915b64d71e950a6c9e3187017d462d4f5940cad889414af05c
6
+ metadata.gz: ab36a730b55d55dee3c9eeb2420573fb4fd25542c81206e66960f38fc6a3655674e747a74901625f598a6afec3f457047fa48c9531d7e74ecc30d2eae36a0a50
7
+ data.tar.gz: 62d6910efdf106bb1243f99fa871238b03a7eb7b9834a70f34e64066965f436d77012586d962e1e774a208c06bc432843d7084780a70c44864ae24963e4e5cb2
@@ -1,6 +1,30 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## 2.5.2 - 2017-09-29
5
+ ### Feature
6
+ - Add mockable class methods to relations.
7
+ - In ActiveRecord model comment Macro `ActiveMocker.safe_methods` now allow class_methods
8
+ ```ruby
9
+ ActiveMocker.safe_methods(*instance_methods, scopes: [], instance_methods: [], class_methods: [])
10
+ ```
11
+
12
+ ### Enhancement
13
+ - Better error message when calling mockable method. Shows RSpec syntax to stub method.
14
+ ```ruby
15
+ Unknown implementation for mock method: UserMock.new_remember_token
16
+ Stub method to continue.
17
+
18
+ RSpec:
19
+ allow(
20
+ UserMock
21
+ ).to receive(:new_remember_token).and_return(:some_expected_result)
22
+ ```
23
+
24
+ ### Removed
25
+ - `ActiveMocker::MockAbilities` required by "active_mocker/deprecated_components/mock_abilities"
26
+ - `mock_method('ClassName')` required by "active_mocker/deprecated_components/rspec" Use `active_mocker.mocks.find('ClassName')` instead
27
+
4
28
  ## 2.5.1 - 2017-07-21
5
29
  ### Feature
6
30
  - Support ActiveRecord v5.1 when generating under that version delete_all does not accept any arguments.
data/README.md CHANGED
@@ -6,7 +6,15 @@
6
6
  [![Gittip](http://img.shields.io/gittip/zeisler.svg)](https://www.gittip.com/zeisler/)
7
7
 
8
8
  ## Description
9
- ActiveMocker creates mock classes from ActiveRecord models, allowing your test suite to run at breakneck speed. This can be done by not loading Rails or hitting a database. The models are read dynamically and statically so that ActiveMocker can generate a Ruby file to require within a test. The mock file can be run by itself and comes with a partial implementation of ActiveRecord. Attributes and associations can be used the same as in ActiveRecord. Methods have the same argument signature but raise a NotImplementedError when called, allowing you to stub it with a mocking framework, like RSpec. Mocks are regenerated when the schema is modified so your mocks won't go stale, preventing the case where your units tests pass but production code fails.
9
+ ActiveMocker creates mock classes from ActiveRecord models,
10
+ allowing your test suite to run at breakneck speed.
11
+ This is done by not loading Rails or hitting the database.
12
+ The models are read dynamically/statically so that ActiveMocker can generate a Ruby file to require within a test.
13
+ The mock file can be run standalone and comes with many use parts of ActiveRecord included.
14
+ Attributes and associations can be used the same as in ActiveRecord.
15
+ Method signatures can be brought over for stubbing or ActiveMocker friendly code can be brought over in it's entirety.
16
+ Mocks are regenerated when the schema is modified so your mocks won't go stale,
17
+ preventing the case where your units tests pass but production code fails.
10
18
 
11
19
  Examples from a real apps
12
20
 
@@ -221,7 +229,7 @@ ActiveMocker::LoadedMocks.features.enable(:stub_active_record_exceptions)
221
229
  Be careful that it does not contain anything that ActiveMocker cannot run.
222
230
 
223
231
  ```ruby
224
- # ActiveMocker.safe_methods(scopes: [], instance_methods: [:full_name])
232
+ # ActiveMocker.safe_methods(scopes: [], instance_methods: [:full_name], class_methods: [])
225
233
  class User
226
234
  def full_name
227
235
  "#{first_name} + #{last_name}"
@@ -12,6 +12,7 @@ require "active_mocker/loaded_mocks"
12
12
  require "active_mocker/mock/hash_process"
13
13
  require "active_mocker/mock/collection"
14
14
  require "active_mocker/mock/queries"
15
+ require "active_mocker/mock/mockable_method"
15
16
  require "active_mocker/mock/relation"
16
17
  require "active_mocker/mock/mock_relation"
17
18
  require "active_mocker/mock/association"
@@ -5,6 +5,8 @@ module ActiveMocker
5
5
  include TemplateMethods
6
6
  extend Queries
7
7
  extend AliasAttribute
8
+ extend MockableMethod
9
+ include MockableMethod
8
10
 
9
11
  def self.inherited(subclass)
10
12
  ActiveMocker::LoadedMocks.send(:add, subclass)
@@ -155,16 +157,6 @@ module ActiveMocker
155
157
  end
156
158
  raise UpdateMocksError.new(name, version, ActiveMocker::Mock::VERSION) if version != ActiveMocker::Mock::VERSION
157
159
  end
158
-
159
- # @deprecated
160
- def call_mock_method(method:, caller:, arguments: [])
161
- is_implemented(method, "::", caller)
162
- end
163
-
164
- # @deprecated
165
- def is_implemented(method, type, call_stack)
166
- raise NotImplementedError, "#{type}#{method} for Class: #{name}. To continue stub the method.", call_stack
167
- end
168
160
  end
169
161
 
170
162
  # @deprecated
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveMocker
4
+ module MockableMethod
5
+ private
6
+
7
+ def __am_raise_not_mocked_error(method:, caller:, type:)
8
+ variable_name = if is_a?(Relation)
9
+ "#{self.class.name.underscore.split("/").first}_relation"
10
+ elsif type == "#"
11
+ "#{self.class.name.underscore}_record"
12
+ else
13
+ name
14
+ end
15
+
16
+ message = <<-ERROR.strip_heredoc
17
+ Unknown implementation for mock method: #{variable_name}.#{method}
18
+ Stub method to continue.
19
+
20
+ RSpec:
21
+ allow(
22
+ #{variable_name}
23
+ ).to receive(:#{method}).and_return(:some_expected_result)
24
+ ERROR
25
+
26
+ raise NotImplementedError, message, caller
27
+ end
28
+ end
29
+ end
@@ -2,6 +2,7 @@
2
2
  module ActiveMocker
3
3
  class Relation < Collection
4
4
  include Queries
5
+ include MockableMethod
5
6
 
6
7
  def initialize(collection = [])
7
8
  super
@@ -18,14 +19,14 @@ module ActiveMocker
18
19
  @from_limit
19
20
  end
20
21
 
22
+ def name
23
+ self.class.name
24
+ end
25
+
21
26
  private
22
27
 
23
28
  def set_from_limit
24
29
  @from_limit = true
25
30
  end
26
-
27
- def name
28
- self.class.name
29
- end
30
31
  end
31
32
  end
@@ -9,9 +9,9 @@ module ActiveMocker
9
9
  :modules_constants,
10
10
  :class_methods,
11
11
  :attributes,
12
- :scopes,
13
12
  :recreate_class_method_calls,
14
13
  :defined_methods,
14
+ :scopes,
15
15
  :associations,
16
16
  ].freeze
17
17
 
@@ -25,20 +25,21 @@ module ActiveMocker
25
25
  def create_method(m, type)
26
26
  plural_type = (type.to_s + "s").to_sym
27
27
  if safe_methods[plural_type].include?(m)
28
- raise "ActiveMocker.safe_methods(class_methods: []) is currently unsupported." if type == :method
29
- def_method = class_introspector.parsed_source.defs.detect { |meth| meth.name == m }
28
+ def_type = type == :method ? :class_defs : :defs
29
+ def_method = class_introspector.parsed_source.public_send(def_type).detect { |meth| meth.name == m }
30
30
  Method.new(
31
31
  m,
32
32
  def_method.arguments,
33
33
  def_method.body
34
34
  )
35
35
  else
36
+ type_symbol = type == :method ? "::" : "#"
36
37
  Method.new(
37
38
  m,
38
39
  ReverseParameters.new(
39
40
  class_introspector.get_class.send(type, m).parameters
40
41
  ).parameters,
41
- "call_mock_method(method: __method__, caller: Kernel.caller, arguments: [])"
42
+ "__am_raise_not_mocked_error(method: __method__, caller: Kernel.caller, type: '#{type_symbol}')"
42
43
  )
43
44
  end
44
45
  end
@@ -19,10 +19,13 @@ module ActiveMocker
19
19
  if safe_methods[:scopes].include?(name)
20
20
  find_scope_body_from_ast(name)
21
21
  else
22
- "#{class_name}.send(:call_mock_method, " \
23
- "method: '#{name}', " \
24
- "caller: Kernel.caller, " \
25
- "arguments: [#{arguments.arguments}])"
22
+ <<-METHOD
23
+ __am_raise_not_mocked_error(
24
+ method: "#{name}",
25
+ caller: Kernel.caller,
26
+ type: "::"
27
+ )
28
+ METHOD
26
29
  end
27
30
  end
28
31
 
@@ -7,7 +7,7 @@ class <%= class_name + mock_append_name %> < <%= parent_class_inspector.parent_m
7
7
  <%= partials.class_methods %>
8
8
  <%= partials.attributes %>
9
9
  <%= partials.associations %>
10
- <%= partials.scopes %>
11
10
  <%= partials.recreate_class_method_calls %>
12
11
  <%= partials.defined_methods %>
12
+ <%= partials.scopes %>
13
13
  end
@@ -3,8 +3,12 @@
3
3
  <%= method.body %>
4
4
  end
5
5
  <% end -%>
6
+ module ClassMethods
6
7
  <% class_methods.each do |method| -%>
7
- def self.<%= method.name %><%= "(#{method.arguments})" unless method.arguments.blank? %>
8
+ def <%= method.name %><%= "(#{method.arguments})" unless method.arguments.blank? %>
8
9
  <%= method.body %>
9
10
  end
10
11
  <% end -%>
12
+ end
13
+
14
+ extend ClassMethods
@@ -14,6 +14,7 @@ end
14
14
 
15
15
  class ScopeRelation < ActiveMocker::Association
16
16
  include <%= class_name + mock_append_name %>::Scopes
17
+ include ClassMethods
17
18
  end
18
19
 
19
20
  def self.__new_relation__(collection)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module ActiveMocker
3
- VERSION = "2.5.1"
3
+ VERSION = "2.5.2"
4
4
  module Mock
5
5
  VERSION = "2" # This increments when breaking changes happen in the generated mocks
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_mocker
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.1
4
+ version: 2.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dustin Zeisler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-21 00:00:00.000000000 Z
11
+ date: 2017-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -212,8 +212,6 @@ files:
212
212
  - lib/active_mocker/attribute_types/enum.rb
213
213
  - lib/active_mocker/attribute_types/register.rb
214
214
  - lib/active_mocker/config.rb
215
- - lib/active_mocker/deprecated_components/mock_abilities.rb
216
- - lib/active_mocker/deprecated_components/rspec.rb
217
215
  - lib/active_mocker/display_errors.rb
218
216
  - lib/active_mocker/error_object.rb
219
217
  - lib/active_mocker/file_path_to_ruby_class.rb
@@ -244,6 +242,7 @@ files:
244
242
  - lib/active_mocker/mock/has_one.rb
245
243
  - lib/active_mocker/mock/hash_process.rb
246
244
  - lib/active_mocker/mock/mock_relation.rb
245
+ - lib/active_mocker/mock/mockable_method.rb
247
246
  - lib/active_mocker/mock/object_inspect.rb
248
247
  - lib/active_mocker/mock/queries.rb
249
248
  - lib/active_mocker/mock/records.rb
@@ -1,106 +0,0 @@
1
- # frozen_string_literal: true
2
- module ActiveMocker
3
- # @deprecated to keep using until removal, require this file.
4
- module MockAbilities
5
- module InstanceAndClassMethods
6
- def mock_instance_method(method, exe_bind = false, &block)
7
- mockable_instance_methods[method.to_sym] = MockMethod.new(block, exe_bind)
8
- end
9
-
10
- alias stub_instance_method mock_instance_method
11
-
12
- def clear_mocked_methods
13
- mockable_instance_methods.clear
14
- mockable_class_methods.clear
15
- end
16
-
17
- # @deprecated
18
- def clear_mock
19
- clear_mocked_methods
20
- delete_all
21
- end
22
-
23
- private
24
-
25
- def mockable_instance_methods
26
- @mockable_instance_methods ||= {}
27
- end
28
-
29
- def class_name
30
- return name if self.class == Class
31
- self.class
32
- end
33
-
34
- def is_implemented(val, method, type, call_stack)
35
- raise NotImplementedError, "#{type}#{method} for Class: #{class_name}. To continue stub the method.", call_stack if val.nil?
36
- end
37
-
38
- def execute_block(method)
39
- return instance_exec(method.arguments, &method.block) if method.exe_bind
40
- method.block.call(*method.arguments)
41
- end
42
- end
43
-
44
- def self.included(base)
45
- base.extend(ClassMethods)
46
- end
47
-
48
- def self.prepended(base)
49
- class << base
50
- prepend(ClassMethods)
51
- end
52
- end
53
-
54
- module ClassMethods
55
- include InstanceAndClassMethods
56
-
57
- def mockable_class_methods
58
- @mockable_class_methods ||= {}
59
- end
60
-
61
- def mock_class_method(method, exe_bind = false, &block)
62
- mockable_class_methods[method.to_sym] = MockMethod.new(block, exe_bind)
63
- end
64
-
65
- alias stub_class_method mock_class_method
66
-
67
- def call_mock_method(method:, caller:, arguments: [])
68
- mock_method = mockable_class_methods[method.to_sym]
69
- is_implemented(mock_method, method, "::", caller)
70
- mock_method.arguments = arguments
71
- execute_block(mock_method)
72
- end
73
-
74
- private :call_mock_method
75
- end
76
-
77
- include InstanceAndClassMethods
78
-
79
- def call_mock_method(method:, caller:, arguments: [])
80
- mock_method = mockable_instance_methods[method.to_sym]
81
- mock_method = self.class.send(:mockable_instance_methods)[method.to_sym] if mock_method.nil?
82
- is_implemented(mock_method, method, '#', caller)
83
- mock_method.arguments = arguments
84
- execute_block mock_method
85
- end
86
-
87
- private :call_mock_method
88
-
89
- def clear_mocked_methods
90
- mockable_instance_methods.clear
91
- end
92
-
93
- class MockMethod
94
- attr_accessor :block, :arguments, :exe_bind
95
-
96
- def initialize(block, exe_bind)
97
- @block = block
98
- @exe_bind = exe_bind
99
- end
100
- end
101
- end
102
-
103
- class Base
104
- prepend MockAbilities
105
- end
106
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
- require "active_mocker/rspec"
3
-
4
- module ActiveMocker
5
- module Rspec
6
- # @deprecated method, will be removed in version 2.1
7
- # Use +active_mocker.mocks.find('ClassName')+ instead
8
- # To keep using until removal, require this file.
9
- def mock_class(*args)
10
- active_mocker.mocks.find(*args)
11
- end
12
- end
13
- end