muack 0.7.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,10 +2,10 @@
2
2
  require 'muack/test'
3
3
 
4
4
  describe Muack::AnyInstanceOf do
5
- klass = Class.new{ def f; 0; end }
5
+ klass = Class.new{ def f; 0; end; private; def g; 1; end }
6
6
 
7
7
  should 'mock any_instance_of' do
8
- any_instance_of(klass){ |instance| mock(instance).say{ true } }
8
+ any_instance_of(klass){ |inst| mock(inst).say{ true } }
9
9
  obj = klass.new
10
10
  obj.say .should.eq true
11
11
  obj.respond_to?(:say).should.eq true
@@ -13,16 +13,33 @@ describe Muack::AnyInstanceOf do
13
13
  obj.respond_to?(:say).should.eq false
14
14
  end
15
15
 
16
+ should 'mock any_instance_of with instance_exec' do
17
+ any_instance_of(klass){ |inst|
18
+ mock(inst).say.returns(:instance_exec => true){ f } }
19
+ obj = klass.new
20
+ obj.say .should.eq obj.f
21
+ Muack.verify .should.eq true
22
+ obj.respond_to?(:say).should.eq false
23
+ end
24
+
16
25
  should 'proxy any_instance_of' do
17
- any_instance_of(klass){ |instance| mock(instance).f.proxy }
26
+ any_instance_of(klass){ |inst| mock(inst).f }
18
27
  obj = klass.new
19
28
  obj.f .should.eq 0
20
29
  Muack.verify.should.eq true
21
30
  obj.f .should.eq 0
22
31
  end
23
32
 
24
- should 'proxy any_instance_of with a block' do
25
- any_instance_of(klass){ |instance| mock(instance).f{ |i| i+1 }.proxy }
33
+ should 'proxy any_instance_of for private methods' do
34
+ any_instance_of(klass){ |inst| mock(inst).g.peek_return{|i|i+1} }
35
+ obj = klass.new
36
+ obj.__send__(:g).should.eq 2
37
+ Muack.verify .should.eq true
38
+ obj.__send__(:g).should.eq 1
39
+ end
40
+
41
+ should 'proxy any_instance_of with peek_return' do
42
+ any_instance_of(klass){ |inst| mock(inst).f.peek_return{|i|i+1} }
26
43
  obj = klass.new
27
44
  obj.f .should.eq 1
28
45
  Muack.verify.should.eq true
@@ -30,8 +47,8 @@ describe Muack::AnyInstanceOf do
30
47
  end
31
48
 
32
49
  should 'proxy with multiple any_instance_of call' do
33
- any_instance_of(klass){ |instance| mock(instance).f{ |i| i+1 }.proxy }
34
- any_instance_of(klass){ |instance| mock(instance).f{ |i| i+2 }.proxy }
50
+ any_instance_of(klass){ |inst| mock(inst).f.peek_return{ |i| i+1 } }
51
+ any_instance_of(klass){ |inst| mock(inst).f.peek_return{ |i| i+2 } }
35
52
  obj = klass.new
36
53
  obj.f.should.eq 1
37
54
  obj.f.should.eq 2
@@ -49,8 +66,15 @@ describe Muack::AnyInstanceOf do
49
66
  obj.f.should.eq 0
50
67
  end
51
68
 
69
+ should 'share the same counts for different instances' do
70
+ times = 2
71
+ any_instance_of(klass){ |inst| mock(inst).f{0}.times(times) }
72
+ times.times{ klass.new.f.should.eq 0 }
73
+ Muack.verify.should.eq true
74
+ end
75
+
52
76
  should 'stub proxy with any_instance_of and spy' do
53
- any_instance_of(klass){ |inst| stub(inst).f{ |i| i+3 }.proxy }
77
+ any_instance_of(klass){ |inst| stub(inst).f.peek_return{ |i| i+3 } }
54
78
  obj = klass.new
55
79
  obj.f.should.eq 3
56
80
  obj.f.should.eq 3
@@ -0,0 +1,40 @@
1
+
2
+ require 'muack/test'
3
+
4
+ describe 'from README.md' do
5
+ readme = File.read(
6
+ "#{File.dirname(File.expand_path(__FILE__))}/../README.md")
7
+ codes = readme.scan(/``` ruby(.+?)```/m).map(&:first)
8
+
9
+ after{ Muack.reset }
10
+
11
+ Context = Module.new{
12
+ def p res
13
+ (@results ||= []) << res
14
+ end
15
+
16
+ def verify expects
17
+ return unless @results
18
+ @results.zip(expects).each do |(res, exp)|
19
+ next if exp == 'ok'
20
+ if exp.start_with?('raise')
21
+ res.should.kind_of eval(exp.sub('raise', ''))
22
+ else
23
+ res.should.eq eval(exp)
24
+ end
25
+ end
26
+ end
27
+ }
28
+
29
+ codes.each.with_index do |code, index|
30
+ should 'pass from README.md #%02d' % index do
31
+ context = Module.new{extend Context}
32
+ begin
33
+ context.instance_eval(code, 'README.md', 0)
34
+ rescue Muack::Failure => e
35
+ context.p e
36
+ end
37
+ context.verify(code.scan(/# (.+)/).map(&:first))
38
+ end
39
+ end
40
+ end
data/test/test_mock.rb CHANGED
@@ -22,6 +22,21 @@ describe Muack::Mock do
22
22
  Obj.to_s.should.eq 'zoo'
23
23
  end
24
24
 
25
+ should 'pass the actual block' do
26
+ mock(Obj).say{ |&block| block.call('Hi') }
27
+ Obj.say{ |msg| msg }.should.eq 'Hi'
28
+ end
29
+
30
+ should 'mock private method and preserve privacy' do
31
+ mock(Obj).private{ 'sai' }
32
+ Obj.respond_to?(:private ).should.eq false
33
+ Obj.respond_to?(:private, true).should.eq true
34
+ Obj.__send__(:private).should.eq 'sai'
35
+ Muack.verify.should.eq true
36
+ Obj.respond_to?(:private ).should.eq false
37
+ Obj.__send__(:private).should.eq 'pri'
38
+ end
39
+
25
40
  should 'mock twice' do
26
41
  mock(Obj).say(true){ Obj.saya }
27
42
  mock(Obj).saya{ 'coo' }
@@ -37,25 +52,31 @@ describe Muack::Mock do
37
52
  Muack.reset
38
53
  end
39
54
 
40
- should 'mock multiple times' do
41
- 3.times{ |i| mock(Obj).say(i){ i } }
42
- 3.times{ |i| Obj.say(i).should.eq i }
55
+ should 'mix mock and stub' do
56
+ mock(Obj).say { 0 }
57
+ stub(Obj).saya{ 1 }
58
+ 3.times{ Obj.saya.should.eq 1 }
59
+ Obj.say .should.eq 0
43
60
  end
44
61
 
45
- should 'mock multiple times with times(n) modifier' do
46
- mock(Obj).say{ 0 }.times(3)
47
- 3.times{ |i| Obj.say.should.eq 0 }
62
+ should 'mix mock and stub with conflicting method, latter wins' do
63
+ stub(Obj).say{0}
64
+ mock(Obj).say{1}
65
+ Obj.say.should.eq 1
48
66
  end
49
67
 
50
- should 'mock 0 times with times(0) modifier' do
51
- mock(Obj).say{ 0 }.times(0).should.kind_of Muack::Modifier
68
+ should 'mix mock and stub with conflicting method, try to hit stub' do
69
+ stub(Obj).say{0}
70
+ mock(Obj).say{1}
71
+ Obj.say.should.eq 1
72
+ lambda{ Obj.say }.should.raise(Muack::Expected)
52
73
  end
53
74
 
54
- should 'mix mock and stub' do
55
- mock(Obj).say { 0 }
56
- stub(Obj).saya{ 1 }
57
- 3.times{ Obj.saya.should.eq 1 }
58
- Obj.say .should.eq 0
75
+ should 'mix mock and stub with conflicting method, mock never called' do
76
+ mock(Obj).say{0}
77
+ stub(Obj).say{1}
78
+ Obj.say.should.eq 1
79
+ lambda{ Muack.verify }.should.raise(Muack::Expected)
59
80
  end
60
81
 
61
82
  should 'unnamed mock' do
@@ -76,16 +97,6 @@ describe Muack::Mock do
76
97
  Muack.verify.should.eq true
77
98
  obj.f .should.eq 0
78
99
  end
79
-
80
- should 'return values with returns with a value' do
81
- mock(Obj).say.returns(0)
82
- Obj.say.should.eq 0
83
- end
84
-
85
- should 'return values with returns with a block' do
86
- mock(Obj).say.returns{0}
87
- Obj.say.should.eq 0
88
- end
89
100
  end
90
101
 
91
102
  describe 'Muack.verify==false' do
@@ -107,7 +118,7 @@ describe Muack::Mock do
107
118
  end
108
119
 
109
120
  should 'have correct message for multiple mocks with the same name' do
110
- 2.times{ mock(Obj).say }
121
+ 2.times{ mock(Obj).say{} }
111
122
  begin
112
123
  3.times{ Obj.say }
113
124
  'never'.should.eq 'reach'
@@ -121,7 +132,7 @@ describe Muack::Mock do
121
132
  end
122
133
 
123
134
  should 'have correct message for mocks with special satisfier' do
124
- mock(Obj).say(anything)
135
+ mock(Obj).say(anything){}
125
136
  begin
126
137
  Obj.say(1)
127
138
  Obj.say(2)
@@ -188,7 +199,7 @@ describe Muack::Mock do
188
199
 
189
200
  should 'show first not enough calls' do
190
201
  mock(Obj).say{ 'boo' }.times(2)
191
- mock(Obj).saya .times(2)
202
+ mock(Obj).saya{} .times(2)
192
203
  begin
193
204
  Obj.say
194
205
  Muack.verify
@@ -0,0 +1,102 @@
1
+
2
+ require 'muack/test'
3
+
4
+ describe Muack::Modifier do
5
+ after do
6
+ Muack.verify.should.eq true
7
+ Muack::EnsureReset.call
8
+ end
9
+
10
+ describe 'times' do
11
+ should 'mock multiple times' do
12
+ 3.times{ |i| mock(Obj).say(i){ i } }
13
+ 3.times{ |i| Obj.say(i).should.eq i }
14
+ end
15
+
16
+ should 'mock multiple times with times(n) modifier' do
17
+ mock(Obj).say{ 0 }.times(3)
18
+ 3.times{ |i| Obj.say.should.eq 0 }
19
+ end
20
+
21
+ should 'mock 0 times with times(0) modifier' do
22
+ mock(Obj).say{ 0 }.times(0).should.kind_of Muack::Modifier
23
+ end
24
+ end
25
+
26
+ describe 'returns' do
27
+ should 'return with lexical scope' do
28
+ mock(Obj).say.returns{0}
29
+ Obj.say.should.eq 0
30
+ end
31
+
32
+ should 'return with dynamic scope' do
33
+ mock(Obj).say.returns(:instance_exec => true){object_id}
34
+ Obj.say.should.eq Obj.object_id
35
+ end
36
+ end
37
+
38
+ describe 'peek_args' do
39
+ should 'with lexical scope' do
40
+ str = 'ff'
41
+ stub(str).to_i.peek_args{16}
42
+ str.to_i.should.eq 255
43
+ end
44
+
45
+ should 'with dynamic scope' do
46
+ str = '16'
47
+ stub(str).to_i.peek_args(:instance_exec => true){Integer(self)}
48
+ str.to_i.should.eq 22
49
+ end
50
+
51
+ should 'modify' do
52
+ str = 'ff'
53
+ stub(str).to_i(is_a(Integer)).peek_args{ |radix| radix * 2 }
54
+ str.to_i(8).should.eq 255
55
+ end
56
+
57
+ should 'preserve args' do
58
+ stub(Obj).say{|*a|a}.with_any_args.peek_args{|*a|a}
59
+ Obj.say(0,1).should.eq [0,1]
60
+ end
61
+
62
+ should 'pass first args' do
63
+ stub(Obj).say{|*a|a}.with_any_args.peek_args{|a|a}
64
+ Obj.say(0,1).should.eq [0]
65
+ end
66
+
67
+ should 'pass nothing with nil' do
68
+ stub(Obj).say{|*a|a}.with_any_args.peek_args{}
69
+ Obj.say(0,1).should.eq []
70
+ end
71
+
72
+ should 'pass nothing with empty array' do
73
+ stub(Obj).say{|*a|a}.with_any_args.peek_args{[]}
74
+ Obj.say(0,1).should.eq []
75
+ end
76
+
77
+ should 'pass an empty array with [[]]' do
78
+ stub(Obj).say{|*a|a}.with_any_args.peek_args{[[]]}
79
+ Obj.say(0,1).should.eq [[]]
80
+ end
81
+ end
82
+
83
+ describe 'peek_return' do
84
+ should 'with lexical scope' do
85
+ str = 'ff'
86
+ stub(str).to_i.peek_return{16}
87
+ str.to_i.should.eq 16
88
+ end
89
+
90
+ should 'with dynamic scope' do
91
+ str = '16'
92
+ stub(str).to_i.peek_return(:instance_exec => true){Integer(self)+1}
93
+ str.to_i.should.eq 17
94
+ end
95
+
96
+ should 'modify' do
97
+ str = 'ff'
98
+ stub(str).to_i(is_a(Integer)).peek_return{ |result| result * 2 }
99
+ str.to_i(16).should.eq 510
100
+ end
101
+ end
102
+ end
data/test/test_proxy.rb CHANGED
@@ -9,57 +9,62 @@ describe Muack::Mock do
9
9
  end
10
10
 
11
11
  should 'proxy with regular method' do
12
- mock(Str).reverse.proxy
12
+ mock(Str).reverse
13
13
  Str.reverse.should.eq 'ooM'
14
14
  end
15
15
 
16
+ should 'proxy with private method' do
17
+ mock(Obj).private.peek_return(&:reverse)
18
+ Obj.__send__(:private).should.eq 'irp'
19
+ end
20
+
16
21
  should 'proxy multiple times' do
17
- 2.times{ mock(Str).reverse.proxy }
22
+ 2.times{ mock(Str).reverse }
18
23
  2.times{ Str.reverse.should.eq 'ooM' }
19
24
  end
20
25
 
21
26
  should 'proxy multiple times with super method' do
22
- 2.times{ mock(Str).class.proxy }
27
+ 2.times{ mock(Str).class }
23
28
  2.times{ Str.class.should.eq String }
24
29
  end
25
30
 
26
31
  should 'return modifier itself for any modifier methods' do
27
- mock(Str).to_s.proxy.returns{ |s| s.reverse }.times(2).
32
+ mock(Str).to_s.peek_return{ |s| s.reverse }.times(2).
28
33
  with_any_args.with_any_args
29
34
  2.times{ Str.to_s.should.eq 'ooM' }
30
35
  end
31
36
 
32
37
  should 'proxy and call the block' do
33
- mock(Obj).method_missing(:inspect){ |str| str.reverse }.proxy
38
+ mock(Obj).method_missing(:inspect).peek_return{ |str| str.reverse }
34
39
  Obj.inspect.should.eq 'jbo'
35
40
  end
36
41
 
37
42
  should 'proxy and call the block with super' do
38
- mock(Str).class{ |k| k.name.reverse }.proxy
43
+ mock(Str).class.peek_return{ |k| k.name.reverse }
39
44
  Str.class.should.eq 'gnirtS'
40
45
  end
41
46
 
42
47
  should 'mock proxy and call, mock proxy and call' do
43
- mock(Obj).class{ |k| k.name.reverse }.proxy
48
+ mock(Obj).class.peek_return{ |k| k.name.reverse }
44
49
  Obj.class.should.eq 'tcejbO'
45
- mock(Obj).class{ |k| k.name.upcase }.proxy
50
+ mock(Obj).class.peek_return{ |k| k.name.upcase }
46
51
  Obj.class.should.eq 'OBJECT'
47
52
  end
48
53
 
49
54
  should 'stub proxy and call, stub proxy and call' do
50
- stub(Obj).kind_of?(Object){ |b| !b }.proxy
55
+ stub(Obj).kind_of?(Object).peek_return{ |b| !b }
51
56
  Obj.kind_of?(Object).should.eq false
52
- stub(Obj).kind_of?(String){ |b| b.to_s }.proxy
57
+ stub(Obj).kind_of?(String).peek_return{ |b| b.to_s }
53
58
  Obj.kind_of?(String).should.eq 'false'
54
59
  end
55
60
 
56
61
  should 'stub proxy with any times' do
57
- stub(Obj).class{ |k| k.name.downcase }.proxy
62
+ stub(Obj).class.peek_return{ |k| k.name.downcase }
58
63
  3.times{ Obj.class.should.eq 'object' }
59
64
  end
60
65
 
61
66
  should 'stub proxy and spy' do
62
- stub(Obj).class{ |k| k.name.downcase }.proxy
67
+ stub(Obj).class.peek_return{ |k| k.name.downcase }
63
68
  Obj.class.should.eq 'object'
64
69
  spy(Obj).class
65
70
  end
@@ -72,7 +77,7 @@ describe Muack::Mock do
72
77
  end
73
78
 
74
79
  should 'raise Expected error if passing unexpected argument' do
75
- mock(Str).reverse.proxy
80
+ mock(Str).reverse
76
81
  Str.reverse.should.eq 'ooM'
77
82
  begin
78
83
  Str.reverse
data/test/test_satisfy.rb CHANGED
@@ -247,6 +247,11 @@ describe Muack::Satisfy do
247
247
  matcher.inspect.should.start_with expected
248
248
  end
249
249
 
250
+ should 'not crash for top-level subclass' do
251
+ Class.new(Muack::Satisfy){ def self.name; 'TopLevel'; end }.new.
252
+ api_name.should.eq 'top_level'
253
+ end
254
+
250
255
  should 'satisfy' do
251
256
  mock(Str).say(satisfy{ |arg| arg % 2 == 0 }){ |arg| arg + 1 }
252
257
  Str.say(14).should.eq 15
@@ -270,7 +275,7 @@ describe Muack::Satisfy do
270
275
  end
271
276
  end
272
277
 
273
- describe Muack::Satisfy::Union do
278
+ describe Muack::Satisfy::Disj do
274
279
  should 'have human readable to_s and inspect' do
275
280
  matcher = is_a(TrueClass) | is_a(FalseClass)
276
281
  expected = 'Muack::API.is_a(TrueClass) | Muack::API.is_a(FalseClass)'
@@ -303,7 +308,7 @@ describe Muack::Satisfy do
303
308
  end
304
309
  end
305
310
 
306
- describe Muack::Satisfy::Inter do
311
+ describe Muack::Satisfy::Conj do
307
312
  should 'have human readable to_s and inspect' do
308
313
  matcher = respond_to(:ancestors) & is_a(Class)
309
314
  expected = 'Muack::API.respond_to(:ancestors) & Muack::API.is_a(Class)'
data/test/test_stub.rb CHANGED
@@ -33,6 +33,11 @@ describe Muack::Stub do
33
33
  Str.say(' ').should.eq 'Hoo'
34
34
  end
35
35
 
36
+ should 'pass the actual block' do
37
+ stub(Obj).say{ |&block| block.call('Hi') }
38
+ Obj.say{ |msg| msg }.should.eq 'Hi'
39
+ end
40
+
36
41
  should 'accept block form' do
37
42
  stub(Obj){ |o| o.say{0}; o.saya{1} }
38
43
  Obj.saya.should.eq 1
@@ -46,13 +51,13 @@ describe Muack::Stub do
46
51
  end
47
52
 
48
53
  should 'work with spy twice' do
49
- stub(Obj).say
54
+ stub(Obj).say{}
50
55
  2.times{ Obj.say.should.eq nil }
51
56
  spy(Obj).say.times(2)
52
57
  end
53
58
 
54
59
  should 'work with spy spy' do
55
- stub(Obj).say
60
+ stub(Obj).say{}
56
61
  2.times{ Obj.say.should.eq nil }
57
62
  2.times{ spy(Obj).say }
58
63
  end
@@ -90,7 +95,7 @@ describe Muack::Stub do
90
95
  end
91
96
 
92
97
  should 'raise Expected if the spy is not satisfied' do
93
- stub(Obj).say
98
+ stub(Obj).say{}
94
99
  spy( Obj).say
95
100
  begin
96
101
  Muack.verify
@@ -105,7 +110,7 @@ describe Muack::Stub do
105
110
  end
106
111
 
107
112
  should 'raise Expected if the spy is not satisfied enough' do
108
- stub(Obj).say
113
+ stub(Obj).say{}
109
114
  Obj.say
110
115
  spy( Obj).say(0)
111
116
  begin
@@ -119,7 +124,7 @@ describe Muack::Stub do
119
124
  end
120
125
 
121
126
  should 'show correct times for under satisfaction' do
122
- stub(Obj).say
127
+ stub(Obj).say{}
123
128
  2.times{ Obj.say }
124
129
  spy( Obj).say.times(3)
125
130
  begin
@@ -135,7 +140,7 @@ describe Muack::Stub do
135
140
  end
136
141
 
137
142
  should 'show correct times for over satisfaction' do
138
- stub(Obj).say
143
+ stub(Obj).say{}
139
144
  2.times{ Obj.say }
140
145
  spy( Obj).say
141
146
  begin