muack 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +15 -0
- data/README.md +134 -46
- data/lib/muack.rb +43 -11
- data/lib/muack/error.rb +6 -0
- data/lib/muack/mock.rb +2 -2
- data/lib/muack/satisfying.rb +186 -0
- data/lib/muack/version.rb +1 -1
- data/muack.gemspec +7 -7
- data/test/test_from_readme.rb +2 -2
- data/test/{test_satisfy.rb → test_satisfying.rb} +187 -80
- metadata +6 -6
- data/lib/muack/satisfy.rb +0 -100
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3bdc0fed7c77d1ef5a925dc20e54857bc2bf279b
|
4
|
+
data.tar.gz: f5be7c8560523fe958c91683d6401e0cfc52f9de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d32c303896f89c12a83a84602e1190062c53d89cb12e10aaff8fb05dc5382d98f82b9e2c8a9a5ae53fee6a284ecdf4bb7b96e10034b33347bce227a071eabbb1
|
7
|
+
data.tar.gz: 3d028e15246b9c8bdd79ab39accfcfb55ec68d5997c502744510a3093a75e8d4e4fa05da936c091fb32cd43dc0429e88cd2841157285fb08dbd3fe2da6d6b1fa
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# CHANGES
|
2
2
|
|
3
|
+
## Muack 1.3.0 -- 2015-05-24
|
4
|
+
|
5
|
+
### Incompatible changes
|
6
|
+
|
7
|
+
* `Muack::API.match` is renamed to `Muack::API.matching`
|
8
|
+
* `Muack::API.respond_to` is renamed to `Muack::API.responding_to`
|
9
|
+
* `Muack::API.hash_including` is renamed to `Muack::API.having`
|
10
|
+
* `Muack::API.satisfy` is renamed to `Muack::API.satisfying`
|
11
|
+
* `Muack::Satisy` is renamed to `Muack::Satisying`
|
12
|
+
|
13
|
+
### Enhancement
|
14
|
+
|
15
|
+
* `Muack::API.where` is added
|
16
|
+
* `Muack::API.allowing` is added
|
17
|
+
|
3
18
|
## Muack 1.2.0 -- 2015-03-10
|
4
19
|
|
5
20
|
* Now stubs could be overwritten. Input from @mz026
|
data/README.md
CHANGED
@@ -59,9 +59,9 @@ end
|
|
59
59
|
|
60
60
|
There are 3 parts in Muack, which are:
|
61
61
|
|
62
|
-
* Mocks
|
63
|
-
* Mocks Modifiers
|
64
|
-
* Arguments Verifiers (
|
62
|
+
* [Mocks](#mocks)
|
63
|
+
* [Mocks Modifiers](#mocks-modifiers)
|
64
|
+
* [Arguments Verifiers (Satisfying)](#arguments-verifiers-satisfying)
|
65
65
|
|
66
66
|
Mocks are objects with injected methods which we could observe, and mocks
|
67
67
|
modifiers are telling how we want to observe the mocks, and finally argument
|
@@ -290,6 +290,44 @@ You might also want to use `peek_args` and `peek_return` modifier along with
|
|
290
290
|
proxies in order to slightly tweak the original implementation. Jump to
|
291
291
|
_Muack as a mocky patching library_ section for more detail.
|
292
292
|
|
293
|
+
#### Partial mode
|
294
|
+
|
295
|
+
Occasionally we would want to fake some of the values inside a hash, but
|
296
|
+
we don't want to interfere with the other values in that hash, and we also
|
297
|
+
don't want to modify it directly, or we'll need to make sure to restore it
|
298
|
+
after the tests.
|
299
|
+
|
300
|
+
Partial mode is not really a mode, but a combination of using proxy mode and
|
301
|
+
the [pattern matching mechanism specialized in stubs][pattern-matching].
|
302
|
+
Suppose we want to stub `ENV` (which is not a hash but you get the idea),
|
303
|
+
enabling some of the flags inside tests without really setting it, we'll do:
|
304
|
+
|
305
|
+
``` ruby
|
306
|
+
@user = ENV['USER']
|
307
|
+
p ENV['NDEBUG'] # nil
|
308
|
+
|
309
|
+
stub(ENV)[is_a(String)] #- NOTE: NEED TO DEFINE THIS PROXY FIRST
|
310
|
+
stub(ENV)['NDEBUG'].returns{ '1' } #- `returns` workaround Ruby syntax
|
311
|
+
|
312
|
+
p ENV['NDEBUG'] # '1'
|
313
|
+
p ENV['USER'] # @user
|
314
|
+
p Muack.verify # true
|
315
|
+
p ENV['NDEBUG'] # nil
|
316
|
+
```
|
317
|
+
|
318
|
+
Note that in order to make this work, proxy should be defined first. Because
|
319
|
+
stubs are searched in Last In First Out (LIFO) order, it would first check
|
320
|
+
if the key is matching `'NDEBUG'` in this case. If it's not matched, then
|
321
|
+
search the next one. Eventually it would reach to the first stub, which
|
322
|
+
we put `is_a(String)` there so it must match, and return the original value
|
323
|
+
inside `ENV`.
|
324
|
+
|
325
|
+
If the order is reversed, then it would always return the original value,
|
326
|
+
because the proxy would always match, and Muack would stop searching the
|
327
|
+
next stub.
|
328
|
+
|
329
|
+
[pattern-matching]: #arguments-verifiers-satisfy
|
330
|
+
|
293
331
|
#### any_instance_of mode
|
294
332
|
|
295
333
|
We only talked about mocking a specific object, but never mentioned what if
|
@@ -635,7 +673,7 @@ p Muack.verify # true
|
|
635
673
|
We could also omit `|_|` if we don't care about the original return value
|
636
674
|
in the above example.
|
637
675
|
|
638
|
-
### Arguments Verifiers (
|
676
|
+
### Arguments Verifiers (Satisfying)
|
639
677
|
|
640
678
|
If we're not passing any arguments to the injected method we define, then
|
641
679
|
basically we're saying that there's no arguments should be passed to the
|
@@ -688,25 +726,13 @@ raise a `Muack::Unexpected` and list the candidates for us.
|
|
688
726
|
|
689
727
|
However, What if we don't want to be so exact? Then we should use verifiers.
|
690
728
|
We'll introduce each of them in next section. Note that verifiers
|
691
|
-
are not recursive though. If you need complex
|
729
|
+
are not recursive though. If you need complex arguments verification,
|
692
730
|
you'll need to use `satisfy` verifier which you could give an arbitrary
|
693
731
|
block to verify anything.
|
694
732
|
|
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
733
|
#### anything
|
708
734
|
|
709
|
-
`anything` is a wildcard
|
735
|
+
`anything` is a wildcard arguments verifier. It matches anything.
|
710
736
|
Although this actually verifies nothing, we could still think of
|
711
737
|
this as an arity verifier. Since one anything is not two anythings.
|
712
738
|
|
@@ -718,15 +744,27 @@ p obj.say(true) # true
|
|
718
744
|
p Muack.verify # true
|
719
745
|
```
|
720
746
|
|
721
|
-
####
|
747
|
+
#### is_a
|
722
748
|
|
723
|
-
`
|
749
|
+
`is_a` would check if the argument is a kind of the given class.
|
750
|
+
Actually, it's calling `kind_of?` underneath.
|
751
|
+
|
752
|
+
``` ruby
|
753
|
+
obj = Object.new
|
754
|
+
mock(obj).say(is_a(String)){ |arg| arg }
|
755
|
+
p obj.say('something') # 'something'
|
756
|
+
p Muack.verify # true
|
757
|
+
```
|
758
|
+
|
759
|
+
#### matching
|
760
|
+
|
761
|
+
`matching` would check the argument with `match` method. Usually this is
|
724
762
|
used with regular expression, but anything which responds to `match`
|
725
763
|
should work.
|
726
764
|
|
727
765
|
``` ruby
|
728
766
|
obj = Object.new
|
729
|
-
mock(obj).say(
|
767
|
+
mock(obj).say(matching(/\w+/)){ |arg| arg }
|
730
768
|
p obj.say('Hi') # 'Hi'
|
731
769
|
p Muack.verify # true
|
732
770
|
```
|
@@ -735,18 +773,6 @@ Note that please don't pass the regular expression directly without
|
|
735
773
|
wrapping it with a match verifier, or how do we distinguish if we
|
736
774
|
really want to make sure the argument is exactly the regular expression?
|
737
775
|
|
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
776
|
#### including
|
751
777
|
|
752
778
|
`including` would check if the actual argument includes the given value
|
@@ -771,36 +797,98 @@ p obj.say(0) # 0
|
|
771
797
|
p Muack.verify # true
|
772
798
|
```
|
773
799
|
|
774
|
-
####
|
800
|
+
#### responding_to
|
775
801
|
|
776
|
-
`
|
802
|
+
`responding_to` would check if the actual argument would be responding to
|
777
803
|
the given message, checked via `respond_to?`, also known as duck typing.
|
778
804
|
|
779
805
|
``` ruby
|
780
806
|
obj = Object.new
|
781
|
-
mock(obj).say(
|
807
|
+
mock(obj).say(responding_to(:size)){ |arg| arg }
|
782
808
|
p obj.say([]) # []
|
783
809
|
p Muack.verify # true
|
784
810
|
```
|
785
811
|
|
786
|
-
Note that you could give multiple messages to `
|
812
|
+
Note that you could give multiple messages to `responding_to`.
|
787
813
|
|
788
814
|
``` ruby
|
789
815
|
obj = Object.new
|
790
|
-
mock(obj).say(
|
816
|
+
mock(obj).say(responding_to(:size, :reverse)){ |arg| arg }
|
791
817
|
p obj.say([]) # []
|
792
818
|
p Muack.verify # true
|
793
819
|
```
|
794
820
|
|
795
|
-
####
|
821
|
+
#### where
|
822
|
+
|
823
|
+
`where` would check if the actual argument matches given specification.
|
824
|
+
|
825
|
+
``` ruby
|
826
|
+
obj = Object.new
|
827
|
+
mock(obj).say(where(:a => is_a(Fixnum))){ |arg| arg }
|
828
|
+
p obj.say(:a => 0) # {:a => 0}
|
829
|
+
p Muack.verify # true
|
830
|
+
```
|
831
|
+
|
832
|
+
Note that this could be recursive.
|
833
|
+
|
834
|
+
``` ruby
|
835
|
+
obj = Object.new
|
836
|
+
mock(obj).say(where(:a => {:b => [is_a(Fixnum)]})){ |arg| arg[:a] }
|
837
|
+
p obj.say(:a => {:b => [0]}) # {:b => [0]}
|
838
|
+
p Muack.verify # true
|
839
|
+
```
|
840
|
+
|
841
|
+
#### having
|
842
|
+
|
843
|
+
`having` would check if the actual argument is a superset of given
|
844
|
+
specification.
|
845
|
+
|
846
|
+
``` ruby
|
847
|
+
obj = Object.new
|
848
|
+
mock(obj).say(having(:a => 0)){ |arg| arg }
|
849
|
+
p obj.say(:a => 0, :b => 1) # {:a => 0, :b => 1}
|
850
|
+
p Muack.verify # true
|
851
|
+
```
|
852
|
+
|
853
|
+
Note that this could be recursive.
|
854
|
+
|
855
|
+
``` ruby
|
856
|
+
obj = Object.new
|
857
|
+
mock(obj).say(having(:a => {:b => [is_a(Fixnum)]})){ |arg| arg[:c] }
|
858
|
+
p obj.say(:a => {:b => [1]}, :c => 2) # 2
|
859
|
+
p Muack.verify # true
|
860
|
+
```
|
861
|
+
|
862
|
+
#### allowing
|
863
|
+
|
864
|
+
`allowing` would check if the actual argument is a subset of given
|
865
|
+
specification.
|
866
|
+
|
867
|
+
``` ruby
|
868
|
+
obj = Object.new
|
869
|
+
mock(obj).say(allowing(:a => 0, :b => [1])){ |arg| arg }
|
870
|
+
p obj.say(:a => 0) # {:a => 0}
|
871
|
+
p Muack.verify # true
|
872
|
+
```
|
873
|
+
|
874
|
+
Note that this could be recursive.
|
875
|
+
|
876
|
+
``` ruby
|
877
|
+
obj = Object.new
|
878
|
+
mock(obj).say(allowing(:a => {:b => is_a(Fixnum), :c => 1})){ |arg| arg[:a] }
|
879
|
+
p obj.say(:a => {:b => 2}) # {:b => 2}
|
880
|
+
p Muack.verify # true
|
881
|
+
```
|
882
|
+
|
883
|
+
#### satisfying
|
796
884
|
|
797
|
-
`
|
885
|
+
`satisfying` accepts a block to let you do arbitrary verification.
|
798
886
|
nil and false are considered false, otherwise true, just like in
|
799
887
|
regular if expression.
|
800
888
|
|
801
889
|
``` ruby
|
802
890
|
obj = Object.new
|
803
|
-
mock(obj).say(
|
891
|
+
mock(obj).say(satisfying{ |arg| arg % 2 == 0 }){ |arg| arg }
|
804
892
|
p obj.say(0) # 0
|
805
893
|
p Muack.verify # true
|
806
894
|
```
|
@@ -837,7 +925,7 @@ class implements each method. We could use conjunction for this.
|
|
837
925
|
|
838
926
|
``` ruby
|
839
927
|
obj = Object.new
|
840
|
-
mock(obj).say(is_a(Enumerable) &
|
928
|
+
mock(obj).say(is_a(Enumerable) & responding_to(:each)){}.times(3)
|
841
929
|
p obj.say( [] ) # nil
|
842
930
|
p obj.say( {} ) # nil
|
843
931
|
p obj.say(0..1) # nil
|
@@ -1055,9 +1143,9 @@ verifiers. For example, we could do this to check if the food is frozen:
|
|
1055
1143
|
Food = Class.new
|
1056
1144
|
User = Class.new{ attr_accessor :food }
|
1057
1145
|
|
1058
|
-
FoodFrozen = Class.new(Muack::
|
1059
|
-
def
|
1060
|
-
|
1146
|
+
FoodFrozen = Class.new(Muack::Satisfying) do
|
1147
|
+
def match actual_arg
|
1148
|
+
actual_arg.frozen?
|
1061
1149
|
end
|
1062
1150
|
end
|
1063
1151
|
|
@@ -1072,7 +1160,7 @@ p u.food = Food.new.freeze # ok
|
|
1072
1160
|
p u.food = Food.new # raise Muack::Unexpected
|
1073
1161
|
```
|
1074
1162
|
|
1075
|
-
Please check _Arguments Verifiers (
|
1163
|
+
Please check _Arguments Verifiers (Satisfying)_ section for more argument
|
1076
1164
|
verifiers details.
|
1077
1165
|
|
1078
1166
|
[dm-core]: https://github.com/datamapper/dm-core
|
data/lib/muack.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
|
2
2
|
require 'muack/session'
|
3
|
-
require 'muack/
|
3
|
+
require 'muack/satisfying'
|
4
4
|
|
5
5
|
module Muack
|
6
6
|
def self.verify obj=nil
|
@@ -46,20 +46,16 @@ module Muack
|
|
46
46
|
if block_given? then yield(ret) else ret end
|
47
47
|
end
|
48
48
|
|
49
|
-
def is_a klass
|
50
|
-
Muack::IsA.new(klass)
|
51
|
-
end
|
52
|
-
|
53
49
|
def anything
|
54
50
|
Muack::Anything.new
|
55
51
|
end
|
56
52
|
|
57
|
-
def
|
58
|
-
Muack::
|
53
|
+
def is_a klass
|
54
|
+
Muack::IsA.new(klass)
|
59
55
|
end
|
60
56
|
|
61
|
-
def
|
62
|
-
Muack::
|
57
|
+
def matching regexp
|
58
|
+
Muack::Matching.new(regexp)
|
63
59
|
end
|
64
60
|
|
65
61
|
def including element
|
@@ -70,12 +66,48 @@ module Muack
|
|
70
66
|
Muack::Within.new(range_or_array)
|
71
67
|
end
|
72
68
|
|
69
|
+
def responding_to *msg
|
70
|
+
Muack::RespondingTo.new(*msg)
|
71
|
+
end
|
72
|
+
|
73
|
+
def where spec
|
74
|
+
Muack::Where.new(spec)
|
75
|
+
end
|
76
|
+
|
77
|
+
def having spec
|
78
|
+
Muack::Having.new(spec)
|
79
|
+
end
|
80
|
+
|
81
|
+
def allowing spec
|
82
|
+
Muack::Allowing.new(spec)
|
83
|
+
end
|
84
|
+
|
85
|
+
def satisfying &block
|
86
|
+
Muack::Satisfying.new(&block)
|
87
|
+
end
|
88
|
+
|
89
|
+
def match regexp
|
90
|
+
$stderr.puts("Muack::API.match is deprecated." \
|
91
|
+
" Use Muack::API.matching instead.")
|
92
|
+
matching(regexp)
|
93
|
+
end
|
94
|
+
|
73
95
|
def respond_to *msg
|
74
|
-
Muack::
|
96
|
+
$stderr.puts("Muack::API.respond_to is deprecated." \
|
97
|
+
" Use Muack::API.responding_to instead.")
|
98
|
+
responding_to(*msg)
|
99
|
+
end
|
100
|
+
|
101
|
+
def hash_including spec
|
102
|
+
$stderr.puts("Muack::API.hash_including is deprecated." \
|
103
|
+
" Use Muack::API.having instead.")
|
104
|
+
having(spec)
|
75
105
|
end
|
76
106
|
|
77
107
|
def satisfy &block
|
78
|
-
Muack::
|
108
|
+
$stderr.puts("Muack::API.satisfy is deprecated." \
|
109
|
+
" Use Muack::API.satisfying instead.")
|
110
|
+
satisfying(&block)
|
79
111
|
end
|
80
112
|
end
|
81
113
|
end
|
data/lib/muack/error.rb
CHANGED
data/lib/muack/mock.rb
CHANGED
@@ -194,12 +194,12 @@ module Muack
|
|
194
194
|
def __mock_check_args expected_args, actual_args
|
195
195
|
if expected_args == [WithAnyArgs]
|
196
196
|
true
|
197
|
-
elsif expected_args.none?{ |arg| arg.kind_of?(
|
197
|
+
elsif expected_args.none?{ |arg| arg.kind_of?(Satisfying) }
|
198
198
|
expected_args == actual_args
|
199
199
|
|
200
200
|
elsif expected_args.size == actual_args.size
|
201
201
|
expected_args.zip(actual_args).all?{ |(e, a)|
|
202
|
-
if e.kind_of?(
|
202
|
+
if e.kind_of?(Satisfying) then e.match(a) else e == a end
|
203
203
|
}
|
204
204
|
else
|
205
205
|
false
|
@@ -0,0 +1,186 @@
|
|
1
|
+
|
2
|
+
require 'muack/error'
|
3
|
+
|
4
|
+
module Muack
|
5
|
+
class Satisfying < Struct.new(:api_args, :block)
|
6
|
+
def initialize args=nil, &block
|
7
|
+
super(args, block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def match actual_arg
|
11
|
+
!!block.call(actual_arg)
|
12
|
+
end
|
13
|
+
|
14
|
+
def | rhs; Satisfying::Disj.new(self, rhs); end
|
15
|
+
def & rhs; Satisfying::Conj.new(self, rhs); end
|
16
|
+
|
17
|
+
class Disj < Satisfying
|
18
|
+
def initialize lhs, rhs
|
19
|
+
@lhs, @rhs = lhs, rhs
|
20
|
+
end
|
21
|
+
|
22
|
+
def match actual_arg
|
23
|
+
@lhs.match(actual_arg) || @rhs.match(actual_arg)
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s; "#{@lhs} | #{@rhs}"; end
|
27
|
+
alias_method :inspect, :to_s
|
28
|
+
end
|
29
|
+
|
30
|
+
class Conj < Satisfying
|
31
|
+
def initialize lhs, rhs
|
32
|
+
@lhs, @rhs = lhs, rhs
|
33
|
+
end
|
34
|
+
|
35
|
+
def match actual_arg
|
36
|
+
@lhs.match(actual_arg) && @rhs.match(actual_arg)
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_s; "#{@lhs} & #{@rhs}"; end
|
40
|
+
alias_method :inspect, :to_s
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s
|
44
|
+
"Muack::API.#{api_name}(#{api_args.map(&:inspect).join(', ')})"
|
45
|
+
end
|
46
|
+
alias_method :inspect, :to_s
|
47
|
+
|
48
|
+
def api_name
|
49
|
+
(self.class.name || 'Unknown')[/(::)*(\w+)$/, 2].
|
50
|
+
gsub(/([A-Z][a-z]*)+?(?=[A-Z][a-z]*)/, '\\1_').downcase
|
51
|
+
end
|
52
|
+
|
53
|
+
def api_args
|
54
|
+
super || [block || method(:match)]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class Anything < Satisfying
|
59
|
+
def initialize
|
60
|
+
super([])
|
61
|
+
end
|
62
|
+
|
63
|
+
def match _
|
64
|
+
true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class IsA < Satisfying
|
69
|
+
def initialize klass
|
70
|
+
super([klass])
|
71
|
+
end
|
72
|
+
|
73
|
+
def match actual_arg
|
74
|
+
actual_arg.kind_of?(api_args.first)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class Matching < Satisfying
|
79
|
+
def initialize regexp
|
80
|
+
super([regexp])
|
81
|
+
end
|
82
|
+
|
83
|
+
def match actual_arg
|
84
|
+
api_args.first.match(actual_arg)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class Including < Satisfying
|
89
|
+
def initialize element
|
90
|
+
super([element])
|
91
|
+
end
|
92
|
+
|
93
|
+
def match actual_arg
|
94
|
+
actual_arg.include?(api_args.first)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class Within < Satisfying
|
99
|
+
def initialize range_or_array
|
100
|
+
super([range_or_array])
|
101
|
+
end
|
102
|
+
|
103
|
+
def match actual_arg
|
104
|
+
api_args.first.include?(actual_arg)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class RespondingTo < Satisfying
|
109
|
+
def initialize *messages
|
110
|
+
super(messages)
|
111
|
+
end
|
112
|
+
|
113
|
+
def match actual_arg
|
114
|
+
api_args.all?{ |msg| actual_arg.respond_to?(msg) }
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
class Where < Satisfying
|
119
|
+
def initialize spec
|
120
|
+
super([spec])
|
121
|
+
end
|
122
|
+
|
123
|
+
def match actual_arg, spec=api_args.first
|
124
|
+
case spec
|
125
|
+
when Hash
|
126
|
+
match_hash(actual_arg, spec)
|
127
|
+
when Array
|
128
|
+
match_array(actual_arg, spec)
|
129
|
+
else
|
130
|
+
raise UnknownSpec.new(spec)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
def match_hash actual_arg, spec
|
136
|
+
(spec.keys | actual_arg.keys).all? do |key|
|
137
|
+
match_value(actual_arg[key], spec[key])
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def match_array actual_arg, spec
|
142
|
+
spec.zip(actual_arg).all? do |(ev, av)|
|
143
|
+
match_value(av, ev)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def match_value av, ev
|
148
|
+
case ev
|
149
|
+
when Satisfying
|
150
|
+
ev.match(av)
|
151
|
+
when Hash
|
152
|
+
match_hash(av, ev)
|
153
|
+
when Array
|
154
|
+
match_array(av, ev)
|
155
|
+
else
|
156
|
+
ev == av
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
class Having < Where
|
162
|
+
def initialize subset
|
163
|
+
super(subset)
|
164
|
+
end
|
165
|
+
|
166
|
+
private
|
167
|
+
def match_hash actual_arg, subset
|
168
|
+
subset.each_key.all? do |key|
|
169
|
+
match_value(actual_arg[key], subset[key])
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
class Allowing < Where
|
175
|
+
def initialize superset
|
176
|
+
super(superset)
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
def match_hash actual_arg, superset
|
181
|
+
actual_arg.each_key.all? do |key|
|
182
|
+
match_value(actual_arg[key], superset[key])
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
data/lib/muack/version.rb
CHANGED
data/muack.gemspec
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: muack 1.
|
2
|
+
# stub: muack 1.3.0 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "muack"
|
6
|
-
s.version = "1.
|
6
|
+
s.version = "1.3.0"
|
7
7
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
9
9
|
s.require_paths = ["lib"]
|
10
10
|
s.authors = ["Lin Jen-Shin (godfat)"]
|
11
|
-
s.date = "2015-
|
11
|
+
s.date = "2015-05-24"
|
12
12
|
s.description = "Muack -- A fast, small, yet powerful mocking library.\n\nInspired by [RR][], and it's 32x times faster (750s vs 23s) than RR\nfor running [Rib][] tests.\n\n[RR]: https://github.com/rr/rr\n[Rib]: https://github.com/godfat/rib"
|
13
13
|
s.email = ["godfat (XD) godfat.org"]
|
14
14
|
s.files = [
|
@@ -29,7 +29,7 @@ Gem::Specification.new do |s|
|
|
29
29
|
"lib/muack/failure.rb",
|
30
30
|
"lib/muack/mock.rb",
|
31
31
|
"lib/muack/modifier.rb",
|
32
|
-
"lib/muack/
|
32
|
+
"lib/muack/satisfying.rb",
|
33
33
|
"lib/muack/session.rb",
|
34
34
|
"lib/muack/spy.rb",
|
35
35
|
"lib/muack/stub.rb",
|
@@ -44,11 +44,11 @@ Gem::Specification.new do |s|
|
|
44
44
|
"test/test_mock.rb",
|
45
45
|
"test/test_modifier.rb",
|
46
46
|
"test/test_proxy.rb",
|
47
|
-
"test/
|
47
|
+
"test/test_satisfying.rb",
|
48
48
|
"test/test_stub.rb"]
|
49
49
|
s.homepage = "https://github.com/godfat/muack"
|
50
50
|
s.licenses = ["Apache License 2.0"]
|
51
|
-
s.rubygems_version = "2.4.
|
51
|
+
s.rubygems_version = "2.4.7"
|
52
52
|
s.summary = "Muack -- A fast, small, yet powerful mocking library."
|
53
53
|
s.test_files = [
|
54
54
|
"test/test_any_instance_of.rb",
|
@@ -57,6 +57,6 @@ Gem::Specification.new do |s|
|
|
57
57
|
"test/test_mock.rb",
|
58
58
|
"test/test_modifier.rb",
|
59
59
|
"test/test_proxy.rb",
|
60
|
-
"test/
|
60
|
+
"test/test_satisfying.rb",
|
61
61
|
"test/test_stub.rb"]
|
62
62
|
end
|
data/test/test_from_readme.rb
CHANGED
@@ -13,7 +13,7 @@ describe 'from README.md' do
|
|
13
13
|
|
14
14
|
def describe desc, &block
|
15
15
|
@executor.describe(desc, &block)
|
16
|
-
@executor.execute(@stat)
|
16
|
+
@executor.execute(Pork.execute_mode, @stat)
|
17
17
|
end
|
18
18
|
|
19
19
|
def results; @results ||= []; end
|
@@ -26,7 +26,7 @@ describe 'from README.md' do
|
|
26
26
|
if exp.start_with?('raise')
|
27
27
|
res.should.kind_of? eval(exp.sub('raise', ''))
|
28
28
|
else
|
29
|
-
res.should.eq
|
29
|
+
res.should.eq instance_eval(exp)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
@@ -1,35 +1,12 @@
|
|
1
1
|
|
2
2
|
require 'muack/test'
|
3
3
|
|
4
|
-
describe Muack::
|
4
|
+
describe Muack::Satisfying do
|
5
5
|
after do
|
6
6
|
Muack.reset
|
7
7
|
Muack::EnsureReset.call
|
8
8
|
end
|
9
9
|
|
10
|
-
describe Muack::IsA do
|
11
|
-
would 'have human readable to_s and inspect' do
|
12
|
-
matcher = is_a(String)
|
13
|
-
expected = 'Muack::API.is_a(String)'
|
14
|
-
matcher.to_s .should.eq expected
|
15
|
-
matcher.inspect.should.eq expected
|
16
|
-
end
|
17
|
-
|
18
|
-
would 'satisfy' do
|
19
|
-
mock(Str).say(is_a(String)){ |arg| arg.reverse }
|
20
|
-
Str.say('Foo').should.eq 'ooF'
|
21
|
-
Muack.verify.should.eq true
|
22
|
-
end
|
23
|
-
|
24
|
-
would 'raise Unexpected error if passing unexpected argument' do
|
25
|
-
mock(Obj).say(is_a(Array)){ 'boo' }
|
26
|
-
e = should.raise(Muack::Unexpected){ Obj.say(false) }
|
27
|
-
e.expected.should.eq 'obj.say(Muack::API.is_a(Array))'
|
28
|
-
e.was .should.eq 'obj.say(false)'
|
29
|
-
e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
10
|
describe Muack::Anything do
|
34
11
|
would 'have human readable to_s and inspect' do
|
35
12
|
matcher = anything
|
@@ -58,63 +35,48 @@ describe Muack::Satisfy do
|
|
58
35
|
end
|
59
36
|
end
|
60
37
|
|
61
|
-
describe Muack::
|
38
|
+
describe Muack::IsA do
|
62
39
|
would 'have human readable to_s and inspect' do
|
63
|
-
matcher =
|
64
|
-
expected = 'Muack::API.
|
40
|
+
matcher = is_a(String)
|
41
|
+
expected = 'Muack::API.is_a(String)'
|
65
42
|
matcher.to_s .should.eq expected
|
66
43
|
matcher.inspect.should.eq expected
|
67
44
|
end
|
68
45
|
|
69
46
|
would 'satisfy' do
|
70
|
-
mock(Str).say(
|
71
|
-
Str.say('
|
47
|
+
mock(Str).say(is_a(String)){ |arg| arg.reverse }
|
48
|
+
Str.say('Foo').should.eq 'ooF'
|
72
49
|
Muack.verify.should.eq true
|
73
50
|
end
|
74
51
|
|
75
52
|
would 'raise Unexpected error if passing unexpected argument' do
|
76
|
-
mock(Obj).say(
|
77
|
-
e = should.raise(Muack::Unexpected){ Obj.say(
|
78
|
-
e.expected.should.eq 'obj.say(Muack::API.
|
79
|
-
e.was .should.eq 'obj.say(
|
53
|
+
mock(Obj).say(is_a(Array)){ 'boo' }
|
54
|
+
e = should.raise(Muack::Unexpected){ Obj.say(false) }
|
55
|
+
e.expected.should.eq 'obj.say(Muack::API.is_a(Array))'
|
56
|
+
e.was .should.eq 'obj.say(false)'
|
80
57
|
e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
|
81
58
|
end
|
82
59
|
end
|
83
60
|
|
84
|
-
describe Muack::
|
61
|
+
describe Muack::Matching do
|
85
62
|
would 'have human readable to_s and inspect' do
|
86
|
-
matcher =
|
87
|
-
expected = 'Muack::API.
|
63
|
+
matcher = matching(/\w/)
|
64
|
+
expected = 'Muack::API.matching(/\w/)'
|
88
65
|
matcher.to_s .should.eq expected
|
89
66
|
matcher.inspect.should.eq expected
|
90
67
|
end
|
91
68
|
|
92
69
|
would 'satisfy' do
|
93
|
-
mock(Str).say(
|
94
|
-
Str.say(
|
95
|
-
Muack.verify.should.eq true
|
96
|
-
end
|
97
|
-
|
98
|
-
would 'satisfy with satisfy' do
|
99
|
-
mock(Str).say(hash_including(:b => is_a(Fixnum))){ |arg| arg[:b] }
|
100
|
-
Str.say(:a => 1, :b => 2).should.eq 2
|
70
|
+
mock(Str).say(matching(/\w/)){ |arg| arg }
|
71
|
+
Str.say('aa').should.eq 'aa'
|
101
72
|
Muack.verify.should.eq true
|
102
73
|
end
|
103
74
|
|
104
75
|
would 'raise Unexpected error if passing unexpected argument' do
|
105
|
-
mock(Obj).say(
|
106
|
-
e = should.raise(Muack::Unexpected){ Obj.say(
|
107
|
-
e.expected.should.eq 'obj.say(Muack::API.
|
108
|
-
e.was .should.eq 'obj.say(
|
109
|
-
e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
|
110
|
-
end
|
111
|
-
|
112
|
-
would 'raise Unexpected error if passing unsatisfied argument' do
|
113
|
-
mock(Obj).say(hash_including(:b => is_a(String))){ 'boo' }
|
114
|
-
e = should.raise(Muack::Unexpected){ Obj.say(:b => 1) }
|
115
|
-
e.expected.should.eq \
|
116
|
-
'obj.say(Muack::API.hash_including({:b=>Muack::API.is_a(String)}))'
|
117
|
-
e.was .should.eq 'obj.say({:b=>1})'
|
76
|
+
mock(Obj).say(matching(/\w/)){ 'boo' }
|
77
|
+
e = should.raise(Muack::Unexpected){ Obj.say('!') }
|
78
|
+
e.expected.should.eq 'obj.say(Muack::API.matching(/\w/))'
|
79
|
+
e.was .should.eq 'obj.say("!")'
|
118
80
|
e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
|
119
81
|
end
|
120
82
|
end
|
@@ -169,68 +131,212 @@ describe Muack::Satisfy do
|
|
169
131
|
end
|
170
132
|
end
|
171
133
|
|
172
|
-
describe Muack::
|
134
|
+
describe Muack::RespondingTo do
|
173
135
|
would 'have human readable to_s and inspect' do
|
174
|
-
matcher =
|
175
|
-
expected = 'Muack::API.
|
136
|
+
matcher = responding_to(:id)
|
137
|
+
expected = 'Muack::API.responding_to(:id)'
|
176
138
|
matcher.to_s .should.start_with? expected
|
177
139
|
matcher.inspect.should.start_with? expected
|
178
140
|
|
179
|
-
matcher =
|
180
|
-
expected = 'Muack::API.
|
141
|
+
matcher = responding_to(:id, :reload)
|
142
|
+
expected = 'Muack::API.responding_to(:id, :reload)'
|
181
143
|
matcher.to_s .should.start_with? expected
|
182
144
|
matcher.inspect.should.start_with? expected
|
183
145
|
end
|
184
146
|
|
185
147
|
would 'satisfy' do
|
186
|
-
mock(Str).say(
|
148
|
+
mock(Str).say(responding_to(:verify, :reset)){ |arg| arg.name }
|
187
149
|
Str.say(Muack).should.eq 'Muack'
|
188
150
|
Muack.verify.should.eq true
|
189
151
|
|
190
|
-
mock(Str).say(
|
152
|
+
mock(Str).say(responding_to(:verify )){ |arg| arg.name }
|
191
153
|
Str.say(Muack).should.eq 'Muack'
|
192
154
|
Muack.verify.should.eq true
|
193
155
|
end
|
194
156
|
|
195
157
|
would 'raise Unexpected error if passing unexpected argument' do
|
196
|
-
mock(Obj).say(
|
158
|
+
mock(Obj).say(responding_to(:nothing)){ 'boo' }
|
197
159
|
e = should.raise(Muack::Unexpected){ Obj.say(0) }
|
198
|
-
e.expected.should.eq 'obj.say(Muack::API.
|
160
|
+
e.expected.should.eq 'obj.say(Muack::API.responding_to(:nothing))'
|
199
161
|
e.was .should.eq 'obj.say(0)'
|
200
162
|
e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
|
201
163
|
end
|
202
164
|
end
|
203
165
|
|
204
|
-
describe Muack::
|
166
|
+
describe Muack::Where do
|
167
|
+
would 'have human readable to_s and inspect' do
|
168
|
+
matcher = where(:b => 2)
|
169
|
+
expected = 'Muack::API.where({:b=>2})'
|
170
|
+
matcher.to_s .should.eq expected
|
171
|
+
matcher.inspect.should.eq expected
|
172
|
+
end
|
173
|
+
|
174
|
+
would 'satisfy' do
|
175
|
+
mock(Str).say(where(:b => 2)){ |arg| arg[:b] }
|
176
|
+
Str.say(:b => 2).should.eq 2
|
177
|
+
Muack.verify.should.eq true
|
178
|
+
end
|
179
|
+
|
180
|
+
would 'satisfy with satisfy' do
|
181
|
+
mock(Str).say(where(:b => is_a(Fixnum))){ |arg| arg[:b] }
|
182
|
+
Str.say(:b => 3).should.eq 3
|
183
|
+
Muack.verify.should.eq true
|
184
|
+
end
|
185
|
+
|
186
|
+
would 'satisfy with satisfy recursive' do
|
187
|
+
spec = where(:a => {:b => is_a(Fixnum)})
|
188
|
+
mock(Str).say(spec){ |arg| arg[:a][:b] }
|
189
|
+
Str.say(:a => {:b => 1}).should.eq 1
|
190
|
+
Muack.verify.should.eq true
|
191
|
+
end
|
192
|
+
|
193
|
+
would 'raise Unexpected error if passing unexpected argument' do
|
194
|
+
mock(Obj).say(where(:b => 2)){ 'boo' }
|
195
|
+
e = should.raise(Muack::Unexpected){ Obj.say(:b => 1) }
|
196
|
+
e.expected.should.eq 'obj.say(Muack::API.where({:b=>2}))'
|
197
|
+
e.was .should.eq 'obj.say({:b=>1})'
|
198
|
+
e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
|
199
|
+
end
|
200
|
+
|
201
|
+
would 'raise Unexpected error if passing unsatisfied argument' do
|
202
|
+
mock(Obj).say(where(:a => 0, :b => is_a(String))){ 'boo' }
|
203
|
+
e = should.raise(Muack::Unexpected){ Obj.say(:a => 0) }
|
204
|
+
e.expected.should.eq \
|
205
|
+
'obj.say(Muack::API.where({:a=>0, :b=>Muack::API.is_a(String)}))'
|
206
|
+
e.was .should.eq 'obj.say({:a=>0})'
|
207
|
+
e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
|
208
|
+
end
|
209
|
+
|
210
|
+
would 'raise Unexpected error if passing unsatisfied argument' do
|
211
|
+
mock(Obj).say(where(:a => 0, :b => is_a(Fixnum))){ 'boo' }
|
212
|
+
e = should.raise(Muack::Unexpected){Obj.say(:a => 0, :b => 1, :c => 2)}
|
213
|
+
e.expected.should.eq \
|
214
|
+
'obj.say(Muack::API.where({:a=>0, :b=>Muack::API.is_a(Fixnum)}))'
|
215
|
+
e.was .should.eq 'obj.say({:a=>0, :b=>1, :c=>2})'
|
216
|
+
e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe Muack::Having do
|
221
|
+
would 'have human readable to_s and inspect' do
|
222
|
+
matcher = having(:b => 2)
|
223
|
+
expected = 'Muack::API.having({:b=>2})'
|
224
|
+
matcher.to_s .should.eq expected
|
225
|
+
matcher.inspect.should.eq expected
|
226
|
+
end
|
227
|
+
|
228
|
+
would 'satisfy' do
|
229
|
+
mock(Str).say(having(:b => 2)){ |arg| arg[:a] }
|
230
|
+
Str.say(:a => 1, :b => 2).should.eq 1
|
231
|
+
Muack.verify.should.eq true
|
232
|
+
end
|
233
|
+
|
234
|
+
would 'satisfy with satisfy' do
|
235
|
+
mock(Str).say(having(:b => is_a(Fixnum))){ |arg| arg[:b] }
|
236
|
+
Str.say(:a => 1, :b => 2).should.eq 2
|
237
|
+
Muack.verify.should.eq true
|
238
|
+
end
|
239
|
+
|
240
|
+
would 'satisfy with satisfy recursive' do
|
241
|
+
spec = having(:a => {:b => is_a(Fixnum)})
|
242
|
+
mock(Str).say(spec){ |arg| arg[:a][:c] }
|
243
|
+
Str.say(:a => {:b => 1, :c => 2}, :d => 3).should.eq 2
|
244
|
+
Muack.verify.should.eq true
|
245
|
+
end
|
246
|
+
|
247
|
+
would 'raise Unexpected error if passing unexpected argument' do
|
248
|
+
mock(Obj).say(having(:b => 2)){ 'boo' }
|
249
|
+
e = should.raise(Muack::Unexpected){ Obj.say(:a => 1) }
|
250
|
+
e.expected.should.eq 'obj.say(Muack::API.having({:b=>2}))'
|
251
|
+
e.was .should.eq 'obj.say({:a=>1})'
|
252
|
+
e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
|
253
|
+
end
|
254
|
+
|
255
|
+
would 'raise Unexpected error if passing unsatisfied argument' do
|
256
|
+
mock(Obj).say(having(:a => 0, :b => is_a(Fixnum))){ 'boo' }
|
257
|
+
e = should.raise(Muack::Unexpected){ Obj.say(:b => 1) }
|
258
|
+
e.expected.should.eq \
|
259
|
+
'obj.say(Muack::API.having({:a=>0, :b=>Muack::API.is_a(Fixnum)}))'
|
260
|
+
e.was .should.eq 'obj.say({:b=>1})'
|
261
|
+
e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
describe Muack::Allowing do
|
266
|
+
would 'have human readable to_s and inspect' do
|
267
|
+
matcher = allowing(:b => 2)
|
268
|
+
expected = 'Muack::API.allowing({:b=>2})'
|
269
|
+
matcher.to_s .should.eq expected
|
270
|
+
matcher.inspect.should.eq expected
|
271
|
+
end
|
272
|
+
|
273
|
+
would 'satisfy' do
|
274
|
+
mock(Str).say(allowing(:a => 0, :b => 1)){ |arg| arg[:a] }
|
275
|
+
Str.say(:a => 0).should.eq 0
|
276
|
+
Muack.verify.should.eq true
|
277
|
+
end
|
278
|
+
|
279
|
+
would 'satisfy with satisfy' do
|
280
|
+
mock(Str).say(allowing(:a => is_a(Fixnum), :b => 1)){ |arg| arg[:a] }
|
281
|
+
Str.say(:a => 0).should.eq 0
|
282
|
+
Muack.verify.should.eq true
|
283
|
+
end
|
284
|
+
|
285
|
+
would 'satisfy with satisfy recursive' do
|
286
|
+
spec = allowing(:a => {:b => is_a(Fixnum), :c => 1}, :d => 2)
|
287
|
+
mock(Str).say(spec){ |arg| arg[:a][:b] }
|
288
|
+
Str.say(:a => {:b => 0}).should.eq 0
|
289
|
+
Muack.verify.should.eq true
|
290
|
+
end
|
291
|
+
|
292
|
+
would 'raise Unexpected error if passing unexpected argument' do
|
293
|
+
mock(Obj).say(allowing(:b => 2)){ 'boo' }
|
294
|
+
e = should.raise(Muack::Unexpected){ Obj.say(:a => 1) }
|
295
|
+
e.expected.should.eq 'obj.say(Muack::API.allowing({:b=>2}))'
|
296
|
+
e.was .should.eq 'obj.say({:a=>1})'
|
297
|
+
e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
|
298
|
+
end
|
299
|
+
|
300
|
+
would 'raise Unexpected error if passing unsatisfied argument' do
|
301
|
+
mock(Obj).say(allowing(:b => is_a(String))){ 'boo' }
|
302
|
+
e = should.raise(Muack::Unexpected){ Obj.say(:b => '1', :c => 2) }
|
303
|
+
e.expected.should.eq \
|
304
|
+
'obj.say(Muack::API.allowing({:b=>Muack::API.is_a(String)}))'
|
305
|
+
e.was .should.eq 'obj.say({:b=>"1", :c=>2})'
|
306
|
+
e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
describe Muack::Satisfying do
|
205
311
|
would 'have human readable to_s and inspect' do
|
206
|
-
matcher =
|
207
|
-
expected = 'Muack::API.
|
312
|
+
matcher = satisfying{ |arg| arg % 2 == 0 }
|
313
|
+
expected = 'Muack::API.satisfying(#<Proc:'
|
208
314
|
matcher.to_s .should.start_with? expected
|
209
315
|
matcher.inspect.should.start_with? expected
|
210
316
|
end
|
211
317
|
|
212
318
|
would 'not crash for top-level subclass' do
|
213
|
-
Class.new(Muack::
|
319
|
+
Class.new(Muack::Satisfying){ def self.name; 'TopLevel'; end }.new.
|
214
320
|
api_name.should.eq 'top_level'
|
215
321
|
end
|
216
322
|
|
217
323
|
would 'satisfy' do
|
218
|
-
mock(Str).say(
|
324
|
+
mock(Str).say(satisfying{ |arg| arg % 2 == 0 }){ |arg| arg + 1 }
|
219
325
|
Str.say(14).should.eq 15
|
220
326
|
Muack.verify.should.eq true
|
221
327
|
Muack::EnsureReset.call
|
222
328
|
end
|
223
329
|
|
224
330
|
would 'raise Unexpected error if passing unexpected argument' do
|
225
|
-
mock(Obj).say(
|
331
|
+
mock(Obj).say(satisfying{ |arg| arg % 2 == 0 }){ 'boo' }
|
226
332
|
e = should.raise(Muack::Unexpected){ Obj.say(1) }
|
227
|
-
e.expected.should.start_with? 'obj.say(Muack::API.
|
333
|
+
e.expected.should.start_with? 'obj.say(Muack::API.satisfying(#<Proc:'
|
228
334
|
e.was .should.eq 'obj.say(1)'
|
229
335
|
e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
|
230
336
|
end
|
231
337
|
end
|
232
338
|
|
233
|
-
describe Muack::
|
339
|
+
describe Muack::Satisfying::Disj do
|
234
340
|
would 'have human readable to_s and inspect' do
|
235
341
|
matcher = is_a(TrueClass) | is_a(FalseClass)
|
236
342
|
expected = 'Muack::API.is_a(TrueClass) | Muack::API.is_a(FalseClass)'
|
@@ -246,26 +352,27 @@ describe Muack::Satisfy do
|
|
246
352
|
end
|
247
353
|
|
248
354
|
would 'raise Unexpected error if passing unexpected argument' do
|
249
|
-
mock(Obj).say(within('0'..'1') |
|
355
|
+
mock(Obj).say(within('0'..'1') | matching(/a/)){ 'boo' }
|
250
356
|
e = should.raise(Muack::Unexpected){ Obj.say('2') }
|
251
357
|
e.expected.should.eq \
|
252
|
-
'obj.say(Muack::API.within("0".."1") | Muack::API.
|
358
|
+
'obj.say(Muack::API.within("0".."1") | Muack::API.matching(/a/))'
|
253
359
|
e.was .should.eq \
|
254
360
|
'obj.say("2")'
|
255
361
|
e.message .should.eq "\nExpected: #{e.expected}\n but was: #{e.was}"
|
256
362
|
end
|
257
363
|
end
|
258
364
|
|
259
|
-
describe Muack::
|
365
|
+
describe Muack::Satisfying::Conj do
|
260
366
|
would 'have human readable to_s and inspect' do
|
261
|
-
matcher =
|
262
|
-
expected =
|
367
|
+
matcher = responding_to(:ancestors) & is_a(Class)
|
368
|
+
expected =
|
369
|
+
'Muack::API.responding_to(:ancestors) & Muack::API.is_a(Class)'
|
263
370
|
matcher.to_s .should.eq expected
|
264
371
|
matcher.inspect.should.eq expected
|
265
372
|
end
|
266
373
|
|
267
374
|
would 'satisfy' do
|
268
|
-
mock(Str).say(
|
375
|
+
mock(Str).say(responding_to(:ancestors) & is_a(Class)){ |arg| arg.new }
|
269
376
|
Str.say(String).should.eq ''
|
270
377
|
Muack.verify .should.eq true
|
271
378
|
Muack::EnsureReset.call
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: muack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lin Jen-Shin (godfat)
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-05-24 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |-
|
14
14
|
Muack -- A fast, small, yet powerful mocking library.
|
@@ -41,7 +41,7 @@ files:
|
|
41
41
|
- lib/muack/failure.rb
|
42
42
|
- lib/muack/mock.rb
|
43
43
|
- lib/muack/modifier.rb
|
44
|
-
- lib/muack/
|
44
|
+
- lib/muack/satisfying.rb
|
45
45
|
- lib/muack/session.rb
|
46
46
|
- lib/muack/spy.rb
|
47
47
|
- lib/muack/stub.rb
|
@@ -56,7 +56,7 @@ files:
|
|
56
56
|
- test/test_mock.rb
|
57
57
|
- test/test_modifier.rb
|
58
58
|
- test/test_proxy.rb
|
59
|
-
- test/
|
59
|
+
- test/test_satisfying.rb
|
60
60
|
- test/test_stub.rb
|
61
61
|
homepage: https://github.com/godfat/muack
|
62
62
|
licenses:
|
@@ -78,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
78
|
version: '0'
|
79
79
|
requirements: []
|
80
80
|
rubyforge_project:
|
81
|
-
rubygems_version: 2.4.
|
81
|
+
rubygems_version: 2.4.7
|
82
82
|
signing_key:
|
83
83
|
specification_version: 4
|
84
84
|
summary: Muack -- A fast, small, yet powerful mocking library.
|
@@ -89,5 +89,5 @@ test_files:
|
|
89
89
|
- test/test_mock.rb
|
90
90
|
- test/test_modifier.rb
|
91
91
|
- test/test_proxy.rb
|
92
|
-
- test/
|
92
|
+
- test/test_satisfying.rb
|
93
93
|
- test/test_stub.rb
|
data/lib/muack/satisfy.rb
DELETED
@@ -1,100 +0,0 @@
|
|
1
|
-
|
2
|
-
module Muack
|
3
|
-
class Satisfy < Struct.new(:block, :api_args)
|
4
|
-
def match actual_arg
|
5
|
-
!!block.call(actual_arg)
|
6
|
-
end
|
7
|
-
|
8
|
-
def | rhs; Satisfy::Disj.new(self, rhs); end
|
9
|
-
def & rhs; Satisfy::Conj.new(self, rhs); end
|
10
|
-
|
11
|
-
class Disj < Satisfy
|
12
|
-
def initialize lhs, rhs
|
13
|
-
@lhs, @rhs = lhs, rhs
|
14
|
-
super(lambda{ |actual_arg| lhs.match(actual_arg) ||
|
15
|
-
rhs.match(actual_arg) })
|
16
|
-
end
|
17
|
-
|
18
|
-
def to_s; "#{@lhs} | #{@rhs}"; end
|
19
|
-
alias_method :inspect, :to_s
|
20
|
-
end
|
21
|
-
|
22
|
-
class Conj < Satisfy
|
23
|
-
def initialize lhs, rhs
|
24
|
-
@lhs, @rhs = lhs, rhs
|
25
|
-
super(lambda{ |actual_arg| lhs.match(actual_arg) &&
|
26
|
-
rhs.match(actual_arg) })
|
27
|
-
end
|
28
|
-
|
29
|
-
def to_s; "#{@lhs} & #{@rhs}"; end
|
30
|
-
alias_method :inspect, :to_s
|
31
|
-
end
|
32
|
-
|
33
|
-
def to_s
|
34
|
-
"Muack::API.#{api_name}(#{api_args.map(&:inspect).join(', ')})"
|
35
|
-
end
|
36
|
-
alias_method :inspect, :to_s
|
37
|
-
|
38
|
-
def api_name
|
39
|
-
(self.class.name || 'Unknown')[/(::)*(\w+)$/, 2].
|
40
|
-
gsub(/([A-Z][a-z]*)+?(?=[A-Z][a-z]*)/, '\\1_').downcase
|
41
|
-
end
|
42
|
-
|
43
|
-
def api_args
|
44
|
-
super || [block]
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
class IsA < Satisfy
|
49
|
-
def initialize klass
|
50
|
-
super lambda{ |actual_arg| actual_arg.kind_of?(klass) }, [klass]
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
class Anything < Satisfy
|
55
|
-
def initialize
|
56
|
-
super lambda{ |_| true }, []
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
class Match < Satisfy
|
61
|
-
def initialize regexp
|
62
|
-
super lambda{ |actual_arg| regexp.match(actual_arg) }, [regexp]
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
class HashIncluding < Satisfy
|
67
|
-
def initialize hash
|
68
|
-
super lambda{ |actual_arg|
|
69
|
-
actual_arg.values_at(*hash.keys).zip(hash.values).all? do |(av, ev)|
|
70
|
-
if ev.kind_of?(Satisfy)
|
71
|
-
ev.match(av)
|
72
|
-
else
|
73
|
-
ev == av
|
74
|
-
end
|
75
|
-
end
|
76
|
-
}, [hash]
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
class Including < Satisfy
|
81
|
-
def initialize element
|
82
|
-
super lambda{ |actual_arg|
|
83
|
-
actual_arg.include?(element) }, [element]
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
class Within < Satisfy
|
88
|
-
def initialize range_or_array
|
89
|
-
super lambda{ |actual_arg| range_or_array.include?(actual_arg) },
|
90
|
-
[range_or_array]
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
class RespondTo < Satisfy
|
95
|
-
def initialize *messages
|
96
|
-
super lambda{ |actual_arg|
|
97
|
-
messages.all?{ |msg| actual_arg.respond_to?(msg) } }, messages
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|