stubberry 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 76a44be83df94f95993dad5da5a540ec3b5f7d6a3334b45fb9f19d64f11445bd
4
- data.tar.gz: 7644abf117453f0635e8f14899d400f515c3a3ed763a3fff3737aa3ebb24408a
3
+ metadata.gz: 84ce1669272b052fded99ad9ba06ff354ef8dec1891a47e288140b554f159bdc
4
+ data.tar.gz: e113462e1d879af411a08b81dac5f77ce9d5f9341c700b6b4a2559c72dae5368
5
5
  SHA512:
6
- metadata.gz: 7c205abde785d061fab126fe889aa87cf611dc9851697aca91ba3e1ddd3c1d2dcac7ce2e1226f4aa6298027ba521913177547db185382ff77b9d85566e88d003
7
- data.tar.gz: '0579be30cd4c3e44e492f3262417105feeff44fdf48cbaa0ebfffd3b56e8337571051bc6eb50f8dbdf53e433e82e8c0a33bf7fc48ec3a6d38a48b071a320fdb2'
6
+ metadata.gz: dd67bcee9b9ef05fe6fc89c5223fa59560ea2229b3835517463e88543256623fc2568277732e38317e95ee8d2573c4d1da4ad72136da2cd0ba639071a9ddd6cc
7
+ data.tar.gz: 7db15cd29b4d85cbc03a20a701aa693c57c5f11ad8c2d81c1298c0753b84282a639f279f0fa3753e295d40b9a70539dc2631676654d36f34c54e9afe7531a4af
data/.gitignore CHANGED
@@ -6,3 +6,4 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /.idea/
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ # 0.1.1
2
+ * initial gem release
3
+ * Stubberry::Object module with stub_must, stub_must_not, stub_must_all, stub_if_* methods
4
+ * Stubberry::ActiveRecord easy id based stubbing active record objects inside some actions flow
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Stubberry
2
+ Pay attention it has 2Bs and 2Rs in naming :)
2
3
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/stubberry`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
4
+ This gem is planned to be a ultimate sweet collection of stubbing methods for all kinds of testing.
5
+ Feel free to provide any enrichment suggestions.
6
6
 
7
7
  ## Installation
8
8
 
@@ -22,7 +22,95 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- TODO: Write usage instructions here
25
+ Version 0.1 of this gem has two cool sets of stub methods Stubberry::Object and Stubberry::ActiveRecord
26
+
27
+
28
+ ### Stubberry::Object
29
+
30
+ Set of stubbing methods added to an Object class hence available for any class or its instances.
31
+
32
+ ```ruby
33
+
34
+ # a copy/paste of an Objects stub method enriched with
35
+ # raise error functionality whenever stubbed method wasn't called
36
+ # stub_must( name, val_or_callable, *block_args )
37
+
38
+ test 'check call params with a call must happened' do
39
+ class_or_obj.stub_must(:run, -> ( param ) {
40
+ # Now you can be sure: either you have an expected param, OR
41
+ # if call didn't happened you will see a StandardError raised
42
+ assert_equal( param, 1 )
43
+ } ) { class_or_obj.run(1) }
44
+ end
45
+
46
+ ```
47
+
48
+ Rem: I know about Mock object, but I don't like it. You may consider approach with mock/verify better or more object oriented e.t.c.
49
+ But I do like an error to be aligned to the check, running mock.verify some place after check did happened, feels unnatural and uncomfortable to me
50
+
51
+ ```ruby
52
+ # the reverse method of stub_must -- will raise an issue whenever method
53
+ # was called inside a stubbing block, ensures that flow didn't reach given method
54
+ # stub_must_not( name, message = nil )
55
+ test 'call must not happened' do
56
+ class_or_obj.stub_must_not(:run) { class_or_obj.call(1) }
57
+ end
58
+
59
+ # just for fun multiple stub_must in one call
60
+ # stub_must_all( name_to_var_or_callable, &block )
61
+ test 'all calls should happened' do
62
+ class_or_obj.stub_must_all(
63
+ run: true,
64
+ call: -> (param) { assert_equal(param, 1) }
65
+ ) do
66
+ class_or_obj.call(1)
67
+ class_or_obj.run(args)
68
+ end
69
+ end
70
+
71
+ # stub only if respond_to otherwise just execute block.
72
+ # It's a really rare case, I used only once for incompatible gems versions test
73
+ #
74
+ # stub_if_def(name, val_or_callable, *block_args, &block)
75
+ test 'all calls should happened' do
76
+ class_or_obj.stub_if_def( :not_def, -> (param) { assert_equal(param, :param) } ) do
77
+ # when there is nothing to stub, just yield
78
+ :just_yield_this_without_stubbing
79
+ end
80
+ end
81
+
82
+ # stub_must_if_def(name, val_or_callable, *block_args, &block)
83
+ # same as above but with stub_must under the hood
84
+ ```
85
+
86
+ ### Stubberry::ActiveRecord
87
+
88
+ Easy stubbing for ActiveRecord objects, you just need the id and Stubberry will do the rest.
89
+ The cool stuff about these stubbing methods is an independence from the way object retrieved.
90
+ You can get object via find, where or any relation, it doesn't matter.
91
+ Stubbing is based on after_find callback, so whenever object instantiated
92
+ it will be properly stubbed.
93
+
94
+ ```ruby
95
+ # you can stub active record object attributes with stub_orm_attr
96
+
97
+ test 'object attributes will be stubbed in relations' do
98
+ Comment.stub_orm_attr(1, {body: 'ola!'} ) do
99
+ assert_equal( 'ola!', User.first.comments.where(id: 1).take.body )
100
+ assert_equal( 'ola!', Comment.find(1).body )
101
+ end
102
+ end
103
+
104
+ # you can stub active record object method with stub_orm_method
105
+ test 'object with a given id got method stubbed' do
106
+ Comment.stub_orm_method(1, join: -> ( other ) {
107
+ assert_equal( other.id, 2 )
108
+ } ) do
109
+ User.first.comments.where(id: 1).each{ _1.join( Comment.find(2) ) }
110
+ end
111
+ end
112
+ ```
113
+
26
114
 
27
115
  ## Development
28
116
 
@@ -32,7 +120,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
120
 
33
121
  ## Contributing
34
122
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/stubberry. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/stubberry/blob/master/CODE_OF_CONDUCT.md).
123
+ Bug reports and pull requests are welcome on GitHub at https://github.com/alekseyl/stubberry. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/stubberry/blob/master/CODE_OF_CONDUCT.md).
36
124
 
37
125
 
38
126
  ## License
@@ -0,0 +1,84 @@
1
+ # this module provide two methods for active record classes
2
+ # to easily stub any record attributes and methods disregarding the way
3
+ # record was obtained inside the yielding block, you just need an id.
4
+ #
5
+ # i.e. alternative way of dealing with any record with id could be stub of
6
+ # the specific method like where or find with a given set of params e.t.c.
7
+ # that's a very error prone approach, with stub_orm_* methods we
8
+ # do not care about the way object was obtained as long as after_find
9
+ # callback was executed
10
+ module Stubberry::ActiveRecord
11
+ extend ActiveSupport::Concern
12
+
13
+ # for any active record object for classes included Stubberry::ActiveRecord
14
+ # we adding after_find callback extending object with self.class.extend_any
15
+ # default implementation of self.class.extend_any does nothing
16
+ included do
17
+ after_find {|obj| self.class.extend_any(obj) }
18
+ end
19
+
20
+ module ClassMethods
21
+
22
+ # This method could be used whenever there is a need for stubbing
23
+ # the exact ActiveRecord object attributes inside some execution flow
24
+ # __without__ underlying record change
25
+ def stub_orm_attr(id, obj_or_attributes )
26
+ stub(:extend_any, -> (obj) {
27
+ return unless obj.id == id && obj.is_a?( self )
28
+ obj.assign_attributes( obj_or_attributes.try(:attributes) || obj_or_attributes )
29
+ }) do
30
+ yield
31
+ end
32
+ end
33
+
34
+ # This method could be used whenever there is a need for stubbing
35
+ # the specific Active Record object's methods inside some flow piece
36
+ # with ANY way of object retrieval, making
37
+ def stub_orm_method(id, method, val_or_callable, *block_args )
38
+ stub(:extend_any, -> (obj) {
39
+ return unless obj.id == id && obj.is_a?( self )
40
+ define_stub_method(obj, method, val_or_callable, *block_args )
41
+ }) do
42
+ yield
43
+ end
44
+ ensure
45
+ undef_all(id, method)
46
+ end
47
+
48
+ private_class_method
49
+
50
+ def define_stub_method( object, method, val_or_callable, *block_args )
51
+ old_method = stub_method_name(method, obj: object)
52
+ object.singleton_class.send :alias_method, old_method, method
53
+ object.define_singleton_method method do |*args, &blk|
54
+ if val_or_callable.respond_to? :call
55
+ val_or_callable.call(*args, &blk)
56
+ else
57
+ blk.call(*block_args) if blk
58
+ val_or_callable
59
+ end
60
+ end
61
+ stubbed_objects(old_method) << object
62
+ end
63
+
64
+ def stub_method_name( method, obj: nil, id: nil)
65
+ # __stub_class_method_id
66
+ "__stub_#{to_s}_#{method}_#{obj&.id || id}"
67
+ end
68
+
69
+ def undef_all(id, method)
70
+ old_method = stub_method_name( method, id: id)
71
+ stubbed_objects(old_method).map(&:singleton_class).each do |metaclass|
72
+ metaclass.send :undef_method, method
73
+ metaclass.send :alias_method, method, old_method
74
+ metaclass.send :undef_method, old_method
75
+ end
76
+ end
77
+
78
+ def stubbed_objects(method_name)
79
+ (@@extended_obj ||= {})[method_name] ||= []
80
+ end
81
+
82
+ def extend_any(_obj); :do_nothing end
83
+ end
84
+ end if defined?(ActiveSupport::Concern)
@@ -0,0 +1,84 @@
1
+ module Stubberry::Object
2
+ # a copy/paste of an Objects stub method enriched with
3
+ # raise error functionality whenever stubbed method wasn't called
4
+ def stub_must( name, val_or_callable, *block_args )
5
+ new_name = "__minitest_stub__#{name}"
6
+ call_happened_method_name = "__#{name}_call_happened"
7
+
8
+ metaclass = class << self; self; end
9
+
10
+ if respond_to? name and not methods.map(&:to_s).include? name.to_s then
11
+ metaclass.send :define_method, name do |*args|
12
+ super(*args)
13
+ end
14
+ end
15
+
16
+ metaclass.send :alias_method, new_name, name
17
+
18
+ # this will make a closure without spoiling class with any instance vars and so
19
+ call_happened = []
20
+ metaclass.send :define_method, call_happened_method_name do
21
+ call_happened << true
22
+ end
23
+
24
+ metaclass.send :define_method, name do |*args, &blk|
25
+ __send__(call_happened_method_name)
26
+
27
+ if val_or_callable.respond_to? :call then
28
+ val_or_callable.call(*args, &blk)
29
+ else
30
+ blk.call(*block_args) if blk
31
+ val_or_callable
32
+ end
33
+ end
34
+
35
+ (yield self).tap do
36
+ raise "#{name} wasn't called" if call_happened.length == 0
37
+ end
38
+ ensure
39
+ metaclass.send :undef_method, name
40
+ metaclass.send :alias_method, name, new_name
41
+ metaclass.send :undef_method, new_name
42
+ metaclass.send :undef_method, call_happened_method_name
43
+ end
44
+
45
+ # the reverse method of stub_must -- will raise an issue whenever method
46
+ # was called inside a stubbing block
47
+ def stub_must_not( name, message = nil )
48
+ new_name = "__minitest_stub__#{name}"
49
+
50
+ metaclass = class << self; self; end
51
+
52
+ if respond_to?(name) && !methods.map(&:to_s).include?( name.to_s )
53
+ metaclass.define_method( name ) { | *args | super(*args) }
54
+ end
55
+
56
+ metaclass.alias_method( new_name, name )
57
+ metaclass.define_method( name ) { |*| raise message || "#{name} was called!" }
58
+
59
+ yield self
60
+ ensure
61
+ metaclass.undef_method( name )
62
+ metaclass.alias_method( name, new_name )
63
+ metaclass.undef_method( new_name )
64
+ end
65
+
66
+ # just for fun multiple stub_must in one call
67
+ def stub_must_all( name_to_var_or_callable, &block )
68
+ name_to_var_or_callable.length == 1 ? stub_must( *name_to_var_or_callable.shift, &block )
69
+ : stub_must( *name_to_var_or_callable.shift ) { stub_must_all(name_to_var_or_callable, &block ) }
70
+ end
71
+
72
+ # stub only if respond otherwise just execute
73
+ def stub_if_def(name, val_or_callable, *block_args, &block)
74
+ respond_to?( name ) ? stub(name, val_or_callable, *block_args, &block) : yield
75
+ end
76
+
77
+ # stub_must only if respond otherwise just execute
78
+ def stub_must_if_def(name, val_or_callable, *block_args, &block)
79
+ # stub only if respond otherwise just execute
80
+ respond_to?( name ) ? stub_must(name, val_or_callable, *block_args, &block) : yield
81
+ end
82
+ end
83
+
84
+ Object.include(Stubberry::Object)
@@ -1,3 +1,3 @@
1
1
  module Stubberry
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
data/lib/stubberry.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require "stubberry/version"
2
+ require "stubberry/object"
3
+ require "stubberry/active_record"
2
4
 
3
5
  module Stubberry
4
6
  class Error < StandardError; end
data/stubberry.gemspec CHANGED
@@ -6,8 +6,8 @@ Gem::Specification.new do |spec|
6
6
  spec.authors = ["alekseyl"]
7
7
  spec.email = ["leshchuk@gmail.com"]
8
8
 
9
- spec.summary = %q{This a small set of stub extensions to Object interface.}
10
- spec.description = %q{This a small set of stub extensions to Object interface. There will be stub_must, stub_must_not, stub_if_def, stub_any_ar methods on it }
9
+ spec.summary = %q{Ultimate collection of sweet stub methods for ruby test suits. Lets stub! }
10
+ spec.description = %q{This a ultimate set of stub extensions. Suggest any reasonable subbing and I'll try to merge it. It will start with: stub_must, stub_must_not, stub_if_def and many more }
11
11
  spec.homepage = "https://github.com/alekseyl/stubberry"
12
12
  spec.license = "MIT"
13
13
  spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
@@ -26,4 +26,15 @@ Gem::Specification.new do |spec|
26
26
  spec.bindir = "exe"
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ["lib"]
29
+
30
+ spec.required_ruby_version = '>= 2.4'
31
+ spec.add_development_dependency "activerecord", ">= 6.1"
32
+
33
+ spec.add_development_dependency "bundler", ">= 1"
34
+ spec.add_development_dependency "rake", ">= 12.3.3"
35
+ spec.add_development_dependency "minitest", "~> 5.0"
36
+ spec.add_development_dependency 'sqlite3'
37
+
38
+
39
+ spec.add_development_dependency "ruby_jard"
29
40
  end
metadata CHANGED
@@ -1,17 +1,102 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stubberry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - alekseyl
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-02 00:00:00.000000000 Z
12
- dependencies: []
13
- description: 'This a small set of stub extensions to Object interface. There will
14
- be stub_must, stub_must_not, stub_if_def, stub_any_ar methods on it '
11
+ date: 2021-11-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '6.1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '6.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 12.3.3
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 12.3.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: ruby_jard
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: 'This a ultimate set of stub extensions. Suggest any reasonable subbing
98
+ and I''ll try to merge it. It will start with: stub_must, stub_must_not, stub_if_def
99
+ and many more '
15
100
  email:
16
101
  - leshchuk@gmail.com
17
102
  executables: []
@@ -19,9 +104,8 @@ extensions: []
19
104
  extra_rdoc_files: []
20
105
  files:
21
106
  - ".gitignore"
22
- - ".idea/inspectionProfiles/profiles_settings.xml"
23
- - ".idea/workspace.xml"
24
107
  - ".travis.yml"
108
+ - CHANGELOG.md
25
109
  - CODE_OF_CONDUCT.md
26
110
  - Gemfile
27
111
  - LICENSE.txt
@@ -30,6 +114,8 @@ files:
30
114
  - bin/console
31
115
  - bin/setup
32
116
  - lib/stubberry.rb
117
+ - lib/stubberry/active_record.rb
118
+ - lib/stubberry/object.rb
33
119
  - lib/stubberry/version.rb
34
120
  - stubberry.gemspec
35
121
  homepage: https://github.com/alekseyl/stubberry
@@ -48,7 +134,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
48
134
  requirements:
49
135
  - - ">="
50
136
  - !ruby/object:Gem::Version
51
- version: 2.3.0
137
+ version: '2.4'
52
138
  required_rubygems_version: !ruby/object:Gem::Requirement
53
139
  requirements:
54
140
  - - ">="
@@ -58,5 +144,5 @@ requirements: []
58
144
  rubygems_version: 3.1.4
59
145
  signing_key:
60
146
  specification_version: 4
61
- summary: This a small set of stub extensions to Object interface.
147
+ summary: Ultimate collection of sweet stub methods for ruby test suits. Lets stub!
62
148
  test_files: []
@@ -1,5 +0,0 @@
1
- <component name="InspectionProjectProfileManager">
2
- <settings>
3
- <option name="PROJECT_PROFILE" />
4
- </settings>
5
- </component>
data/.idea/workspace.xml DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="PropertiesComponent">
4
- <property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
5
- <property name="nodejs_npm_path_reset_for_default_project" value="true" />
6
- <property name="settings.editor.selected.configurable" value="org.jetbrains.plugins.ruby.settings.RubyActiveModuleSdkConfigurable" />
7
- </component>
8
- </project>