muack 1.2.0 → 1.3.0
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 +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
|