muack 1.2.0 → 1.5.0

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
- SHA1:
3
- metadata.gz: 2536a6bd8291b8510a652b7e8102c44e4d204586
4
- data.tar.gz: b4ad06b8093fa3f241145a5586c07feb37487bc2
2
+ SHA256:
3
+ metadata.gz: e65f1260993f94d96899086e3975500583ec077bfae332a8fd4cefc5a2c7da49
4
+ data.tar.gz: 736468eb986e1925f8f83973fec00c2142df16ca80aee9ce051bbdc255cbbfc8
5
5
  SHA512:
6
- metadata.gz: e6c120cfe1b64fe2aa6a842de612c49eb7ec04166a1ac083fdc69f44deb6093fdc5e21a651faed82f76de70b8b25f25a94071311e61ef3a7d8a09700b91019ee
7
- data.tar.gz: 692d50e023c30fa16a1906b18233d9c25a32839617c6a5ef951a7056ffced8ed5ed6173b6913e8824605e34aa8e4c26fa6e6832539e1183053f849b5b15b4273
6
+ metadata.gz: d3bb1281eab20185484890205696cbed1d3996ed6392b76e08297af8e742bd76a80f2e3a26fffec265848d18a5373dffd517db6d2127b4e511dfdc5a2b475937
7
+ data.tar.gz: 2c148e33b0dce444708d09a58f6364e160a926f73e5432120fa8668c7ee0dd65c83128e69723673fd6c95bb62db879b8ff3636af29c93e783954f8409a882ebd
@@ -1,11 +1,21 @@
1
-
1
+ sudo: false
2
2
  language: ruby
3
- rvm:
4
- - 2.0
5
- - 2.1
6
- - 2.2
7
- - rbx-2
8
- - jruby
9
3
 
10
- install: 'bundle install --retry=3'
11
- script: 'ruby -r bundler/setup -S rake test'
4
+ install: 'gem update --system; gem install bundler; bundle install --retry=3'
5
+ before_script: unset CI
6
+ script: 'ruby -vwr bundler/setup -S rake test'
7
+
8
+ matrix:
9
+ include:
10
+ - rvm: 2.4
11
+ env: RUBYOPT=--enable-frozen-string-literal
12
+ - rvm: 2.5
13
+ env: RUBYOPT=--enable-frozen-string-literal
14
+ - rvm: 2.6
15
+ env: RUBYOPT=--enable-frozen-string-literal
16
+ - rvm: 2.7
17
+ env: RUBYOPT=--enable-frozen-string-literal
18
+ - rvm: ruby-head
19
+ env: RUBYOPT=--enable-frozen-string-literal
20
+ - rvm: jruby
21
+ env: RUBYOPT=--enable-frozen-string-literal
data/CHANGES.md CHANGED
@@ -1,5 +1,52 @@
1
1
  # CHANGES
2
2
 
3
+ ## Muack 1.5.0 -- 2020-11-28
4
+
5
+ ### Bugs fixed
6
+
7
+ * Properly handle prepended objects
8
+ * Properly restore method visibilities for singleton methods
9
+
10
+ ### Enhancement
11
+
12
+ * Eliminated any potential keyword arguments warnings to be future proof
13
+ * Some major internal restructure
14
+
15
+ ## Muack 1.4.0 -- 2015-11-21
16
+
17
+ ### Incompatible changes / Enhancement
18
+
19
+ * Spies would now do pattern matching like stubs for matching
20
+ method arguments. This could be an incompatible change if you're
21
+ relying on spies checking the order for the same method calls.
22
+ This change would make spies and stubs more similar. If you are
23
+ really into a specific order, use mocks instead.
24
+
25
+ ## Muack 1.3.2 -- 2015-06-11
26
+
27
+ * Fixed a bug for `where`, `having`, and `allowing` which should distinguish
28
+ between `nil` and `undefined` (which does not have a key in a hash)
29
+
30
+ ## Muack 1.3.1 -- 2015-05-27
31
+
32
+ * Fixed a bug for `where`, `having`, and `allowing` which would raise an
33
+ exception whenever the actual value is not a hash or array.
34
+
35
+ ## Muack 1.3.0 -- 2015-05-24
36
+
37
+ ### Incompatible changes
38
+
39
+ * `Muack::API.match` is renamed to `Muack::API.matching`
40
+ * `Muack::API.respond_to` is renamed to `Muack::API.responding_to`
41
+ * `Muack::API.hash_including` is renamed to `Muack::API.having`
42
+ * `Muack::API.satisfy` is renamed to `Muack::API.satisfying`
43
+ * `Muack::Satisy` is renamed to `Muack::Satisying`
44
+
45
+ ### Enhancement
46
+
47
+ * `Muack::API.where` is added
48
+ * `Muack::API.allowing` is added
49
+
3
50
  ## Muack 1.2.0 -- 2015-03-10
4
51
 
5
52
  * Now stubs could be overwritten. Input from @mz026
data/Gemfile CHANGED
@@ -8,7 +8,3 @@ gem 'pork'
8
8
 
9
9
  gem 'simplecov', :require => false if ENV['COV']
10
10
  gem 'coveralls', :require => false if ENV['CI']
11
-
12
- platform :rbx do
13
- gem 'rubysl-singleton' # used in rake
14
- end
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Muack [![Build Status](https://secure.travis-ci.org/godfat/muack.png?branch=master)](http://travis-ci.org/godfat/muack) [![Coverage Status](https://coveralls.io/repos/godfat/muack/badge.png?branch=master)](https://coveralls.io/r/godfat/muack?branch=master)
1
+ # Muack [![Build Status](https://secure.travis-ci.org/godfat/muack.png?branch=master)](http://travis-ci.org/godfat/muack) [![Coverage Status](https://coveralls.io/repos/github/godfat/muack/badge.png)](https://coveralls.io/github/godfat/muack) [![Join the chat at https://gitter.im/godfat/muack](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/godfat/muack)
2
2
 
3
3
  by Lin Jen-Shin ([godfat](http://godfat.org))
4
4
 
@@ -7,6 +7,7 @@ by Lin Jen-Shin ([godfat](http://godfat.org))
7
7
  * [github](https://github.com/godfat/muack)
8
8
  * [rubygems](https://rubygems.org/gems/muack)
9
9
  * [rdoc](http://rdoc.info/github/godfat/muack)
10
+ * [issues](https://github.com/godfat/muack/issues) (feel free to ask for support)
10
11
 
11
12
  ## DESCRIPTION:
12
13
 
@@ -25,7 +26,7 @@ Muack is much simpler and thus much faster and much more consistent.
25
26
 
26
27
  ## REQUIREMENTS:
27
28
 
28
- * Tested with MRI (official CRuby), Rubinius and JRuby.
29
+ * Tested with MRI (official CRuby) and JRuby.
29
30
 
30
31
  ## INSTALLATION:
31
32
 
@@ -39,14 +40,14 @@ Here's a quick example using [Pork][].
39
40
  require 'pork/auto'
40
41
  require 'muack'
41
42
 
42
- include Muack::API
43
-
44
43
  describe 'Hello' do
44
+ include Muack::API
45
+
45
46
  before{ Muack.reset }
46
47
  after { Muack.verify }
47
48
 
48
49
  would 'say world!' do
49
- str = 'Hello'
50
+ str = 'Hello'.dup
50
51
  mock(str).say('!'){ |arg| "World#{arg}" }
51
52
  str.say('!').should.eq 'World!'
52
53
  end
@@ -59,9 +60,9 @@ end
59
60
 
60
61
  There are 3 parts in Muack, which are:
61
62
 
62
- * Mocks
63
- * Mocks Modifiers
64
- * Arguments Verifiers (Satisfy)
63
+ * [Mocks](#mocks)
64
+ * [Mocks Modifiers](#mocks-modifiers)
65
+ * [Arguments Verifiers (Satisfying)](#arguments-verifiers-satisfying)
65
66
 
66
67
  Mocks are objects with injected methods which we could observe, and mocks
67
68
  modifiers are telling how we want to observe the mocks, and finally argument
@@ -98,7 +99,7 @@ p obj.name # 'obj'
98
99
  p Muack.verify # true
99
100
  ```
100
101
 
101
- Which is roughly semantically equivalent to using a stub with a spy:
102
+ Which is similar to using a stub with a spy:
102
103
 
103
104
  ``` ruby
104
105
  obj = Object.new
@@ -143,6 +144,11 @@ p Muack.verify # true
143
144
  However you should not mix mocks and stubs with the same method, or you
144
145
  might encounter some unexpected result. Jump to _Caveat_ for more detail.
145
146
 
147
+ The other differences for stubs and spies, please check
148
+ [Pattern Matching for stubs and spies][pattern-matching].
149
+ In short, stubs and spies would do some kind of pattern matching,
150
+ making the order of the same method irrelevant.
151
+
146
152
  On the other hand, stubs aren't limited to testing. If we want to monkey
147
153
  patching something, stubs could be useful as we don't care how many times
148
154
  the injected methods are called. Jump to _Muack as a mocky patching library_
@@ -167,7 +173,7 @@ affecting the others. This is helpful in the cases of mocking some very
167
173
  basic objects like Time, without causing too much side effect.
168
174
 
169
175
  ``` ruby
170
- name = 'str'
176
+ name = 'str'.dup
171
177
  stub(name).to_s{ 'hi' }
172
178
  stub(Time).new { Time.at(0) }
173
179
  mock(Time).now { Time.new }
@@ -269,7 +275,7 @@ into proxy mode we simply do not provide any block to the injected method,
269
275
  but just name it. Here's an example:
270
276
 
271
277
  ``` ruby
272
- str = 'str'
278
+ str = 'str'.dup
273
279
  mock(str).reverse
274
280
  p str.reverse # 'rts'
275
281
  p Muack.verify # true
@@ -279,7 +285,7 @@ Note that if reverse was not called exactly once, the mock would complain.
279
285
  We could also use stub + spy to do the same thing as well:
280
286
 
281
287
  ``` ruby
282
- str = 'str'
288
+ str = 'str'.dup
283
289
  stub(str).reverse
284
290
  p str.reverse # 'rts'
285
291
  spy(str).reverse
@@ -290,6 +296,44 @@ You might also want to use `peek_args` and `peek_return` modifier along with
290
296
  proxies in order to slightly tweak the original implementation. Jump to
291
297
  _Muack as a mocky patching library_ section for more detail.
292
298
 
299
+ #### Partial mode
300
+
301
+ Occasionally we would want to fake some of the values inside a hash, but
302
+ we don't want to interfere with the other values in that hash, and we also
303
+ don't want to modify it directly, or we'll need to make sure to restore it
304
+ after the tests.
305
+
306
+ Partial mode is not really a mode, but a combination of using proxy mode and
307
+ the [pattern matching mechanism specialized in stubs][pattern-matching].
308
+ Suppose we want to stub `ENV` (which is not a hash but you get the idea),
309
+ enabling some of the flags inside tests without really setting it, we'll do:
310
+
311
+ ``` ruby
312
+ @user = ENV['USER']
313
+ p ENV['NDEBUG'] # nil
314
+
315
+ stub(ENV)[is_a(String)] #- NOTE: NEED TO DEFINE THIS PROXY FIRST
316
+ stub(ENV)['NDEBUG'].returns{ '1' } #- `returns` workaround Ruby syntax
317
+
318
+ p ENV['NDEBUG'] # '1'
319
+ p ENV['USER'] # @user
320
+ p Muack.verify # true
321
+ p ENV['NDEBUG'] # nil
322
+ ```
323
+
324
+ Note that in order to make this work, proxy should be defined first. Because
325
+ stubs are searched in Last In First Out (LIFO) order, it would first check
326
+ if the key is matching `'NDEBUG'` in this case. If it's not matched, then
327
+ search the next one. Eventually it would reach to the first stub, which
328
+ we put `is_a(String)` there so it must match, and return the original value
329
+ inside `ENV`.
330
+
331
+ If the order is reversed, then it would always return the original value,
332
+ because the proxy would always match, and Muack would stop searching the
333
+ next stub.
334
+
335
+ [pattern-matching]: #pattern-matching-for-stubs-and-spies
336
+
293
337
  #### any_instance_of mode
294
338
 
295
339
  We only talked about mocking a specific object, but never mentioned what if
@@ -408,7 +452,7 @@ p Muack.verify # true
408
452
 
409
453
  Note that it does not make sense to specify `times` for stubs, because
410
454
  stubs don't care about times. Spies do, though. So this is also
411
- semantically equivalent to below:
455
+ similar to below:
412
456
 
413
457
  ``` ruby
414
458
  obj = Object.new
@@ -580,7 +624,7 @@ our own behaviour, then we already have full control of the arguments.
580
624
  There's no points to use both. This also applies to `peek_return`.
581
625
 
582
626
  ``` ruby
583
- str = 'ff'
627
+ str = 'ff'.dup
584
628
  mock(str).to_i.with_any_args.peek_args{ |radix| radix * 2 }
585
629
  p str.to_i(8) # 255
586
630
  p Muack.verify # true
@@ -611,7 +655,7 @@ might just want to take a look at the return? Here's an example using
611
655
  `peek_return` to modify the original return value.
612
656
 
613
657
  ``` ruby
614
- str = 'ff'
658
+ str = 'ff'.dup
615
659
  mock(str).to_i.with_any_args.peek_return{ |int| int * 2 }
616
660
  p str.to_i(16) # 510
617
661
  p Muack.verify # true
@@ -635,7 +679,7 @@ p Muack.verify # true
635
679
  We could also omit `|_|` if we don't care about the original return value
636
680
  in the above example.
637
681
 
638
- ### Arguments Verifiers (Satisfy)
682
+ ### Arguments Verifiers (Satisfying)
639
683
 
640
684
  If we're not passing any arguments to the injected method we define, then
641
685
  basically we're saying that there's no arguments should be passed to the
@@ -670,6 +714,8 @@ obj.say{ |msg| p msg } # 'Hi'
670
714
  p Muack.verify # true
671
715
  ```
672
716
 
717
+ #### Pattern Matching for stubs and spies
718
+
673
719
  Moreover, we could also have stubs on the same method for different
674
720
  arguments. We could think of this as a sort of pattern matching, and Muack
675
721
  would try to find the best matched stub for us.
@@ -684,29 +730,18 @@ p Muack.verify # true
684
730
  ```
685
731
 
686
732
  If `obj.find(2)` is called and Muack cannot find a matched stub, it would
687
- raise a `Muack::Unexpected` and list the candidates for us.
733
+ raise a `Muack::Unexpected` and list the candidates for us. This also
734
+ applies to spies.
688
735
 
689
736
  However, What if we don't want to be so exact? Then we should use verifiers.
690
737
  We'll introduce each of them in next section. Note that verifiers
691
- are not recursive though. If you need complex argument verification,
738
+ are not recursive though. If you need complex arguments verification,
692
739
  you'll need to use `satisfy` verifier which you could give an arbitrary
693
740
  block to verify anything.
694
741
 
695
- #### is_a
696
-
697
- `is_a` would check if the argument is a kind of the given class.
698
- Actually, it's calling `kind_of?` underneath.
699
-
700
- ``` ruby
701
- obj = Object.new
702
- mock(obj).say(is_a(String)){ |arg| arg }
703
- p obj.say('something') # 'something'
704
- p Muack.verify # true
705
- ```
706
-
707
742
  #### anything
708
743
 
709
- `anything` is a wildcard argument verifier. It matches anything.
744
+ `anything` is a wildcard arguments verifier. It matches anything.
710
745
  Although this actually verifies nothing, we could still think of
711
746
  this as an arity verifier. Since one anything is not two anythings.
712
747
 
@@ -718,15 +753,27 @@ p obj.say(true) # true
718
753
  p Muack.verify # true
719
754
  ```
720
755
 
721
- #### match
756
+ #### is_a
757
+
758
+ `is_a` would check if the argument is a kind of the given class.
759
+ Actually, it's calling `kind_of?` underneath.
760
+
761
+ ``` ruby
762
+ obj = Object.new
763
+ mock(obj).say(is_a(String)){ |arg| arg }
764
+ p obj.say('something') # 'something'
765
+ p Muack.verify # true
766
+ ```
767
+
768
+ #### matching
722
769
 
723
- `match` would check the argument with `match` method. Usually this is
770
+ `matching` would check the argument with `match` method. Usually this is
724
771
  used with regular expression, but anything which responds to `match`
725
772
  should work.
726
773
 
727
774
  ``` ruby
728
775
  obj = Object.new
729
- mock(obj).say(match(/\w+/)){ |arg| arg }
776
+ mock(obj).say(matching(/\w+/)){ |arg| arg }
730
777
  p obj.say('Hi') # 'Hi'
731
778
  p Muack.verify # true
732
779
  ```
@@ -735,18 +782,6 @@ Note that please don't pass the regular expression directly without
735
782
  wrapping it with a match verifier, or how do we distinguish if we
736
783
  really want to make sure the argument is exactly the regular expression?
737
784
 
738
- #### hash_including
739
-
740
- `hash_including` would check if the given hash is the actual
741
- argument's subset.
742
-
743
- ``` ruby
744
- obj = Object.new
745
- mock(obj).say(hash_including(:a => 0)){ |arg| arg }
746
- p obj.say(:a => 0, :b => 1) # {:a => 0, :b => 1}
747
- p Muack.verify # true
748
- ```
749
-
750
785
  #### including
751
786
 
752
787
  `including` would check if the actual argument includes the given value
@@ -771,36 +806,98 @@ p obj.say(0) # 0
771
806
  p Muack.verify # true
772
807
  ```
773
808
 
774
- #### respond_to
809
+ #### responding_to
775
810
 
776
- `respond_to` would check if the actual argument would be responding to
811
+ `responding_to` would check if the actual argument would be responding to
777
812
  the given message, checked via `respond_to?`, also known as duck typing.
778
813
 
779
814
  ``` ruby
780
815
  obj = Object.new
781
- mock(obj).say(respond_to(:size)){ |arg| arg }
816
+ mock(obj).say(responding_to(:size)){ |arg| arg }
782
817
  p obj.say([]) # []
783
818
  p Muack.verify # true
784
819
  ```
785
820
 
786
- Note that you could give multiple messages to `respond_to`.
821
+ Note that you could give multiple messages to `responding_to`.
787
822
 
788
823
  ``` ruby
789
824
  obj = Object.new
790
- mock(obj).say(respond_to(:size, :reverse)){ |arg| arg }
825
+ mock(obj).say(responding_to(:size, :reverse)){ |arg| arg }
791
826
  p obj.say([]) # []
792
827
  p Muack.verify # true
793
828
  ```
794
829
 
795
- #### satisfy
830
+ #### where
831
+
832
+ `where` would check if the actual argument matches given specification.
833
+
834
+ ``` ruby
835
+ obj = Object.new
836
+ mock(obj).say(where(:a => is_a(Integer))){ |arg| arg }
837
+ p obj.say(:a => 0) # {:a => 0}
838
+ p Muack.verify # true
839
+ ```
840
+
841
+ Note that this could be recursive.
842
+
843
+ ``` ruby
844
+ obj = Object.new
845
+ mock(obj).say(where(:a => {:b => [is_a(Integer)]})){ |arg| arg[:a] }
846
+ p obj.say(:a => {:b => [0]}) # {:b => [0]}
847
+ p Muack.verify # true
848
+ ```
849
+
850
+ #### having
851
+
852
+ `having` would check if the actual argument is a superset of given
853
+ specification.
854
+
855
+ ``` ruby
856
+ obj = Object.new
857
+ mock(obj).say(having(:a => 0)){ |arg| arg }
858
+ p obj.say(:a => 0, :b => 1) # {:a => 0, :b => 1}
859
+ p Muack.verify # true
860
+ ```
861
+
862
+ Note that this could be recursive.
863
+
864
+ ``` ruby
865
+ obj = Object.new
866
+ mock(obj).say(having(:a => {:b => [is_a(Integer)]})){ |arg| arg[:c] }
867
+ p obj.say(:a => {:b => [1]}, :c => 2) # 2
868
+ p Muack.verify # true
869
+ ```
870
+
871
+ #### allowing
872
+
873
+ `allowing` would check if the actual argument is a subset of given
874
+ specification.
875
+
876
+ ``` ruby
877
+ obj = Object.new
878
+ mock(obj).say(allowing(:a => 0, :b => [1])){ |arg| arg }
879
+ p obj.say(:a => 0) # {:a => 0}
880
+ p Muack.verify # true
881
+ ```
882
+
883
+ Note that this could be recursive.
884
+
885
+ ``` ruby
886
+ obj = Object.new
887
+ mock(obj).say(allowing(:a => {:b => is_a(Integer), :c => 1})){ |arg| arg[:a] }
888
+ p obj.say(:a => {:b => 2}) # {:b => 2}
889
+ p Muack.verify # true
890
+ ```
891
+
892
+ #### satisfying
796
893
 
797
- `satisfy` accepts a block to let you do arbitrary verification.
894
+ `satisfying` accepts a block to let you do arbitrary verification.
798
895
  nil and false are considered false, otherwise true, just like in
799
896
  regular if expression.
800
897
 
801
898
  ``` ruby
802
899
  obj = Object.new
803
- mock(obj).say(satisfy{ |arg| arg % 2 == 0 }){ |arg| arg }
900
+ mock(obj).say(satisfying{ |arg| arg % 2 == 0 }){ |arg| arg }
804
901
  p obj.say(0) # 0
805
902
  p Muack.verify # true
806
903
  ```
@@ -837,7 +934,7 @@ class implements each method. We could use conjunction for this.
837
934
 
838
935
  ``` ruby
839
936
  obj = Object.new
840
- mock(obj).say(is_a(Enumerable) & respond_to(:each)){}.times(3)
937
+ mock(obj).say(is_a(Enumerable) & responding_to(:each)){}.times(3)
841
938
  p obj.say( [] ) # nil
842
939
  p obj.say( {} ) # nil
843
940
  p obj.say(0..1) # nil
@@ -1026,7 +1123,7 @@ Consider we have two classes:
1026
1123
 
1027
1124
  ``` ruby
1028
1125
  Food = Class.new
1029
- User = Class.new{ attr_accessor :food }
1126
+ User = Class.new(Struct.new(:food))
1030
1127
  ```
1031
1128
 
1032
1129
  And we could make sure User#food is always a kind of `Food` by putting this
@@ -1053,11 +1150,11 @@ verifiers. For example, we could do this to check if the food is frozen:
1053
1150
 
1054
1151
  ``` ruby
1055
1152
  Food = Class.new
1056
- User = Class.new{ attr_accessor :food }
1153
+ User = Class.new(Struct.new(:food))
1057
1154
 
1058
- FoodFrozen = Class.new(Muack::Satisfy) do
1059
- def initialize
1060
- super lambda{ |actual_arg| actual_arg.frozen? }
1155
+ FoodFrozen = Class.new(Muack::Satisfying) do
1156
+ def match actual_arg
1157
+ actual_arg.frozen?
1061
1158
  end
1062
1159
  end
1063
1160
 
@@ -1072,7 +1169,7 @@ p u.food = Food.new.freeze # ok
1072
1169
  p u.food = Food.new # raise Muack::Unexpected
1073
1170
  ```
1074
1171
 
1075
- Please check _Arguments Verifiers (Satisfy)_ section for more argument
1172
+ Please check _Arguments Verifiers (Satisfying)_ section for more argument
1076
1173
  verifiers details.
1077
1174
 
1078
1175
  [dm-core]: https://github.com/datamapper/dm-core
@@ -1113,8 +1210,8 @@ Or, I am happy to break legacy.
1113
1210
  ## USERS:
1114
1211
 
1115
1212
  * [Rib][]
1116
- * [rest-core](https://github.com/cardinalblue/rest-core)
1117
- * [rest-more](https://github.com/cardinalblue/rest-more)
1213
+ * [rest-core](https://github.com/godfat/rest-core)
1214
+ * [rest-more](https://github.com/godfat/rest-more)
1118
1215
 
1119
1216
  ## CONTRIBUTORS:
1120
1217
 
@@ -1122,9 +1219,9 @@ Or, I am happy to break legacy.
1122
1219
 
1123
1220
  ## LICENSE:
1124
1221
 
1125
- Apache License 2.0
1222
+ Apache License 2.0 (Apache-2.0)
1126
1223
 
1127
- Copyright (c) 2013-2015, Lin Jen-Shin (godfat)
1224
+ Copyright (c) 2013-2020, Lin Jen-Shin (godfat)
1128
1225
 
1129
1226
  Licensed under the Apache License, Version 2.0 (the "License");
1130
1227
  you may not use this file except in compliance with the License.