muack 1.1.1 → 1.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 46ee22af9472ac4c12baeb58afee2b979d6b80d0
4
- data.tar.gz: f155f3f23684f6fdceb3a6e5bc922cebbd151d0b
3
+ metadata.gz: fa29c09257f78580be72e3872fc7d3ef05650e02
4
+ data.tar.gz: 222e4d730c838c6f76d701c0505b41f7b3476d1e
5
5
  SHA512:
6
- metadata.gz: d27fc18f9ef192c19167432c73ca93191af1f747bfe59731eb8621709925da4ae3f33549ad9b493e0627f4d061581cd7fc1b6d818af6f4c93cd09bcd9bf60267
7
- data.tar.gz: 161f8b4a87addc0d0841fcfe6e3a6ad71becb17ff0b2f2e535e0c7e856051225e71f363950c81bae9ee78f9de8a4baa38150312b4ac15ceb23aa60c231bcbff8
6
+ metadata.gz: 3e539ea17a87076e48f85d980ad7e2c58afb91c8c627af09f05266a2811ecf2d22efb7adbc49f117c240ffca3c34a5e95229457ab2d82a7e8174a132aa17798e
7
+ data.tar.gz: 3b2de41a40ab1134c0952ec763423a0a07b0967ce180b076e129ecde0063ddc05853e278cf6b5fb2d0bb36ecb7ac6d612f3471bd3abefa0ff69a8b79fe0660e4
@@ -2,8 +2,8 @@ before_install: 'git submodule update --init'
2
2
  script: 'ruby -r bundler/setup -S rake test'
3
3
 
4
4
  rvm:
5
- - 1.9.3
6
- - 2.0.0
7
- - ruby
5
+ - 1.9
6
+ - 2.0
7
+ - 2.1
8
8
  - rbx-2
9
9
  - jruby
data/CHANGES.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # CHANGES
2
2
 
3
+ ## Muack 1.1.2 -- 2014-11-07
4
+
5
+ * Introduced `Muack::API.coat`.
6
+ See [README.md](README.md#coats) for explanation.
7
+
8
+ * `Muack::Session` is no longer a hash. Hope no one is trying to store
9
+ anything into it so this change would break nothing.
10
+
11
+ * `Muack::Failure` is no longer an Exception, but a StandardError.
12
+
3
13
  ## Muack 1.1.1 -- 2014-05-21
4
14
 
5
15
  It's no longer necessary to make spy the last call. Below now works:
data/Gemfile CHANGED
@@ -4,7 +4,7 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  gem 'rake'
7
- gem 'bacon'
7
+ gem 'pork'
8
8
 
9
9
  platform :rbx do
10
10
  gem 'rubysl-singleton' # used in rake
data/README.md CHANGED
@@ -33,27 +33,27 @@ Muack is much simpler and thus much faster and much more consistent.
33
33
 
34
34
  ## SYNOPSIS:
35
35
 
36
- Here's a quick example using [Bacon][].
36
+ Here's a quick example using [Pork][].
37
37
 
38
38
  ``` ruby
39
- require 'bacon'
39
+ require 'pork/auto'
40
40
  require 'muack'
41
41
 
42
- Bacon::Context.__send__(:include, Muack::API)
42
+ include Muack::API
43
43
 
44
44
  describe 'Hello' do
45
45
  before{ Muack.reset }
46
46
  after { Muack.verify }
47
47
 
48
- should 'say world!' do
48
+ would 'say world!' do
49
49
  str = 'Hello'
50
50
  mock(str).say('!'){ |arg| "World#{arg}" }
51
- str.say('!').should.equal 'World!'
51
+ str.say('!').should.eq 'World!'
52
52
  end
53
53
  end
54
54
  ```
55
55
 
56
- [Bacon]: https://github.com/chneukirchen/bacon
56
+ [Pork]: https://github.com/godfat/pork
57
57
 
58
58
  ### Overview
59
59
 
@@ -71,14 +71,15 @@ Let's explain them one by one.
71
71
 
72
72
  ### Mocks
73
73
 
74
- There are also 3 different kinds of mocks in Muack, which are:
74
+ There are also 4 different kinds of mocks in Muack, which are:
75
75
 
76
76
  * Mocks
77
77
  * Stubs
78
78
  * Spies
79
+ * Coats
79
80
 
80
- You could think of _mocks_ are sort of _stubs_ combined with _spies_. Here's
81
- the inequation:
81
+ You could think of _mocks_ are sort of _stubs_ combined with _spies_.
82
+ Here's the inequation: (we'll talk about _coats_ later)
82
83
 
83
84
  mock >= stub + spy
84
85
 
@@ -183,6 +184,39 @@ p name.to_s # 'str'
183
184
  p Muack.verify # true
184
185
  ```
185
186
 
187
+ ### Coats
188
+
189
+ Now we could talk about coats. It's a kind of mocks but it would wear out
190
+ instead of raising an exception when it's called more than expected times.
191
+ This is useful when we want to restore the original behaviour of a
192
+ particular method at some point. The problem is that we can't simply
193
+ call the original method because it's already mocked! We could workaround
194
+ this by using `Muack.verify` or `Muack.reset` at some point, or let _coats_
195
+ handle that.
196
+
197
+ Here's an example with _coats_:
198
+
199
+ ``` ruby
200
+ coat(Time).now{ Time.at(0) }.times(2)
201
+
202
+ p Time.now.to_i == 0 # true
203
+ p Time.now.to_i == 0 # true
204
+ p Time.now.to_i > 0 # true
205
+ p Muack.verify # true
206
+ ```
207
+
208
+ Without _coats_ we might end up with:
209
+
210
+ ``` ruby
211
+ mock(Time).now{ Time.at(0) }
212
+ mock(Time).now{ Muack.verify(Time); Time.at(0) }
213
+
214
+ p Time.now.to_i == 0 # true
215
+ p Time.now.to_i == 0 # true
216
+ p Time.now.to_i > 0 # true
217
+ p Muack.verify # true
218
+ ```
219
+
186
220
  #### Anonymous mode
187
221
 
188
222
  Sometimes we just want to stub something without a concrete object in mind.
@@ -31,6 +31,11 @@ module Muack
31
31
  if block_given? then yield(ret) else ret end
32
32
  end
33
33
 
34
+ def coat obj=Object.new
35
+ ret = Muack.session.coat(obj)
36
+ if block_given? then yield(ret) else ret end
37
+ end
38
+
34
39
  def spy obj
35
40
  ret = Muack.session.spy(obj)
36
41
  if block_given? then yield(ret) else ret end
@@ -4,5 +4,9 @@ module Muack
4
4
  def inspect
5
5
  "Muack::API.any_instance_of(#{singleton_class})"
6
6
  end
7
+
8
+ # dummies for Muack::Session
9
+ def __mock_verify; true; end
10
+ def __mock_reset ; ; end
7
11
  end
8
12
  end
@@ -0,0 +1,16 @@
1
+
2
+ require 'muack/mock'
3
+
4
+ module Muack
5
+ class Coat < Mock
6
+ # used for mocked object to dispatch mocked method
7
+ def __mock_dispatch msg, actual_args
8
+ defi = super
9
+ if __mock_defis[defi.msg].empty?
10
+ __mock_reset_method(defi)
11
+ __mock_injected.delete(defi.msg)
12
+ end
13
+ defi
14
+ end
15
+ end
16
+ end
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Muack
3
- class Failure < Exception
3
+ class Failure < StandardError
4
4
  attr_reader :expected
5
5
  def build_expected obj, expected_defis
6
6
  @expected = expected_defis.uniq{ |d| [d.msg, d.args] }.map{ |defi|
@@ -112,17 +112,7 @@ module Muack
112
112
 
113
113
  # used for Muack::Session#reset
114
114
  def __mock_reset
115
- __mock_injected.each_value do |defi|
116
- object.singleton_class.module_eval do
117
- remove_method(defi.msg)
118
- # restore original method
119
- if instance_methods(false).include?(defi.original_method) ||
120
- private_instance_methods(false).include?(defi.original_method)
121
- alias_method(defi.msg, defi.original_method)
122
- remove_method(defi.original_method)
123
- end
124
- end
125
- end
115
+ __mock_injected.each_value{ |defi| __mock_reset_method(defi) }
126
116
  end
127
117
 
128
118
  protected # get warnings for private attributes
@@ -136,6 +126,18 @@ module Muack
136
126
  __mock_inject_mock_method(target, defi, privilege)
137
127
  end
138
128
 
129
+ def __mock_reset_method defi
130
+ object.singleton_class.module_eval do
131
+ remove_method(defi.msg)
132
+ # restore original method
133
+ if instance_methods(false).include?(defi.original_method) ||
134
+ private_instance_methods(false).include?(defi.original_method)
135
+ alias_method(defi.msg, defi.original_method)
136
+ remove_method(defi.original_method)
137
+ end
138
+ end
139
+ end
140
+
139
141
  def self.store_original_method klass, defi
140
142
  privilege = if klass.instance_methods(false).include?(defi.msg)
141
143
  :public # TODO: forget about protected methods?
@@ -1,24 +1,29 @@
1
1
 
2
2
  require 'muack/mock'
3
3
  require 'muack/stub'
4
+ require 'muack/coat'
4
5
  require 'muack/spy'
5
6
  require 'muack/any_instance_of'
6
7
 
7
8
  module Muack
8
- class Session < Hash
9
- def mock obj; self["mk #{obj.__id__}"] ||= Mock.new(obj) ; end
10
- def stub obj; self["sb #{obj.__id__}"] ||= Stub.new(obj) ; end
11
- def spy obj; self["sy #{obj.__id__}"] ||= Spy .new(stub(obj)); end
9
+ class Session
10
+ attr_reader :data
11
+ def initialize; @data = {}; end
12
+
13
+ def mock obj; data["mk #{obj.__id__}"] ||= Mock.new(obj) ; end
14
+ def stub obj; data["sb #{obj.__id__}"] ||= Stub.new(obj) ; end
15
+ def coat obj; data["co #{obj.__id__}"] ||= Coat.new(obj) ; end
16
+ def spy obj; data["sy #{obj.__id__}"] ||= Spy .new(stub(obj)); end
12
17
 
13
18
  def any_instance_of kls
14
- (@others ||= {})["ai #{kls.__id__}"] ||= AnyInstanceOf.new(kls)
19
+ data["ai #{kls.__id__}"] ||= AnyInstanceOf.new(kls)
15
20
  end
16
21
 
17
22
  def verify obj=nil
18
23
  if obj
19
24
  with(obj, :[]).all?(&:__mock_verify)
20
25
  else
21
- each_value.all?(&:__mock_verify)
26
+ data.each_value.all?(&:__mock_verify)
22
27
  end
23
28
  end
24
29
 
@@ -26,15 +31,16 @@ module Muack
26
31
  if obj
27
32
  with(obj, :delete).each(&:__mock_reset)
28
33
  else
29
- instance_variable_defined?(:@others) && @others.clear
30
- reverse_each{ |_, m| m.__mock_reset }
31
- clear
34
+ data.reverse_each{ |_, m| m.__mock_reset } # reverse_each_value?
35
+ data.clear
32
36
  end
33
37
  end
34
38
 
35
39
  private
36
40
  def with obj, meth
37
- %w[mk sb sy].map{ |k| __send__(meth, "#{k} #{obj.__id__}") }.compact
41
+ %w[mk sb co sy ai].map{ |k|
42
+ data.__send__(meth, "#{k} #{obj.__id__}")
43
+ }.compact
38
44
  end
39
45
  end
40
46
  end
@@ -1,9 +1,8 @@
1
1
 
2
- require 'bacon'
2
+ require 'pork/auto'
3
3
  require 'muack'
4
4
 
5
- Bacon.summary_on_exit
6
- Bacon::Context.__send__(:include, Muack::API)
5
+ Pork::Executor.__send__(:include, Muack::API)
7
6
 
8
7
  Obj = Object.new
9
8
  Str = 'Moo'
@@ -22,12 +21,6 @@ Muack::EnsureReset = lambda{
22
21
  [Obj, Str].each do |o|
23
22
  o.methods.select{ |m|
24
23
  m.to_s.start_with?('__muack_mock') || m.to_s.start_with?('say')
25
- }.should.empty
24
+ }.should.empty?
26
25
  end
27
26
  }
28
-
29
- module Kernel
30
- def eq? rhs
31
- self == rhs
32
- end
33
- end
@@ -1,4 +1,4 @@
1
1
 
2
2
  module Muack
3
- VERSION = '1.1.1'
3
+ VERSION = '1.1.2'
4
4
  end
@@ -1,14 +1,14 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: muack 1.1.1 ruby lib
2
+ # stub: muack 1.1.2 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "muack"
6
- s.version = "1.1.1"
6
+ s.version = "1.1.2"
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 = "2014-05-21"
11
+ s.date = "2014-11-07"
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 = [
@@ -23,6 +23,7 @@ Gem::Specification.new do |s|
23
23
  "lib/muack.rb",
24
24
  "lib/muack/any_instance_of.rb",
25
25
  "lib/muack/block.rb",
26
+ "lib/muack/coat.rb",
26
27
  "lib/muack/definition.rb",
27
28
  "lib/muack/error.rb",
28
29
  "lib/muack/failure.rb",
@@ -38,6 +39,7 @@ Gem::Specification.new do |s|
38
39
  "task/README.md",
39
40
  "task/gemgem.rb",
40
41
  "test/test_any_instance_of.rb",
42
+ "test/test_coat.rb",
41
43
  "test/test_from_readme.rb",
42
44
  "test/test_mock.rb",
43
45
  "test/test_modifier.rb",
@@ -46,10 +48,11 @@ Gem::Specification.new do |s|
46
48
  "test/test_stub.rb"]
47
49
  s.homepage = "https://github.com/godfat/muack"
48
50
  s.licenses = ["Apache License 2.0"]
49
- s.rubygems_version = "2.2.2"
51
+ s.rubygems_version = "2.4.2"
50
52
  s.summary = "Muack -- A fast, small, yet powerful mocking library."
51
53
  s.test_files = [
52
54
  "test/test_any_instance_of.rb",
55
+ "test/test_coat.rb",
53
56
  "test/test_from_readme.rb",
54
57
  "test/test_mock.rb",
55
58
  "test/test_modifier.rb",
@@ -34,7 +34,7 @@ module Gemgem
34
34
  s.executables = bin_files
35
35
  end
36
36
  spec_create.call(spec)
37
- spec.homepage = "https://github.com/godfat/#{spec.name}"
37
+ spec.homepage ||= "https://github.com/godfat/#{spec.name}"
38
38
  self.spec = spec
39
39
  end
40
40
 
@@ -227,10 +227,6 @@ end # of gem namespace
227
227
  desc 'Run tests'
228
228
  task :test do
229
229
  next if Gemgem.test_files.empty?
230
-
231
- require 'bacon'
232
- Bacon.extend(Bacon::TestUnitOutput)
233
- Bacon.summary_on_exit
234
230
  Gemgem.test_files.each{ |file| require "#{Gemgem.dir}/#{file[0..-4]}" }
235
231
  end
236
232
 
@@ -4,7 +4,7 @@ require 'muack/test'
4
4
  describe Muack::AnyInstanceOf do
5
5
  klass = Class.new{ def f; 0; end; private; def g; 1; end }
6
6
 
7
- should 'mock any_instance_of' do
7
+ would 'mock any_instance_of' do
8
8
  any_instance_of(klass){ |inst| mock(inst).say{ true } }
9
9
  obj = klass.new
10
10
  obj.say .should.eq true
@@ -13,7 +13,7 @@ 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
16
+ would 'mock any_instance_of with instance_exec' do
17
17
  any_instance_of(klass){ |inst|
18
18
  mock(inst).say.returns(:instance_exec => true){ f } }
19
19
  obj = klass.new
@@ -22,7 +22,7 @@ describe Muack::AnyInstanceOf do
22
22
  obj.respond_to?(:say).should.eq false
23
23
  end
24
24
 
25
- should 'proxy any_instance_of' do
25
+ would 'proxy any_instance_of' do
26
26
  any_instance_of(klass){ |inst| mock(inst).f }
27
27
  obj = klass.new
28
28
  obj.f .should.eq 0
@@ -30,7 +30,7 @@ describe Muack::AnyInstanceOf do
30
30
  obj.f .should.eq 0
31
31
  end
32
32
 
33
- should 'proxy any_instance_of for private methods' do
33
+ would 'proxy any_instance_of for private methods' do
34
34
  any_instance_of(klass){ |inst| mock(inst).g.peek_return{|i|i+1} }
35
35
  obj = klass.new
36
36
  obj.__send__(:g).should.eq 2
@@ -38,7 +38,7 @@ describe Muack::AnyInstanceOf do
38
38
  obj.__send__(:g).should.eq 1
39
39
  end
40
40
 
41
- should 'proxy any_instance_of with peek_return' do
41
+ would 'proxy any_instance_of with peek_return' do
42
42
  any_instance_of(klass){ |inst| mock(inst).f.peek_return{|i|i+1} }
43
43
  obj = klass.new
44
44
  obj.f .should.eq 1
@@ -46,7 +46,7 @@ describe Muack::AnyInstanceOf do
46
46
  obj.f .should.eq 0
47
47
  end
48
48
 
49
- should 'proxy with multiple any_instance_of call' do
49
+ would 'proxy with multiple any_instance_of call' do
50
50
  any_instance_of(klass){ |inst| mock(inst).f.peek_return{ |i| i+1 } }
51
51
  any_instance_of(klass){ |inst| mock(inst).f.peek_return{ |i| i+2 } }
52
52
  obj = klass.new
@@ -56,7 +56,7 @@ describe Muack::AnyInstanceOf do
56
56
  obj.f.should.eq 0
57
57
  end
58
58
 
59
- should 'mock with multiple any_instance_of call' do
59
+ would 'mock with multiple any_instance_of call' do
60
60
  any_instance_of(klass){ |inst| mock(inst).f(is_a(Fixnum)){ |i| i+1 } }
61
61
  any_instance_of(klass){ |inst| mock(inst).f(is_a(Fixnum)){ |i| i+2 } }
62
62
  obj = klass.new
@@ -66,14 +66,14 @@ describe Muack::AnyInstanceOf do
66
66
  obj.f.should.eq 0
67
67
  end
68
68
 
69
- should 'share the same counts for different instances' do
69
+ would 'share the same counts for different instances' do
70
70
  times = 2
71
71
  any_instance_of(klass){ |inst| mock(inst).f{0}.times(times) }
72
72
  times.times{ klass.new.f.should.eq 0 }
73
73
  Muack.verify.should.eq true
74
74
  end
75
75
 
76
- should 'stub proxy with any_instance_of and spy' do
76
+ would 'stub proxy with any_instance_of and spy' do
77
77
  any_instance_of(klass){ |inst| stub(inst).f.peek_return{ |i| i+3 } }
78
78
  obj = klass.new
79
79
  obj.f.should.eq 3
@@ -83,35 +83,33 @@ describe Muack::AnyInstanceOf do
83
83
  obj.f.should.eq 0
84
84
  end
85
85
 
86
- should 'stub with any_instance_of and spy under satisfied' do
86
+ would 'stub with any_instance_of and spy under satisfied' do
87
87
  any_instance_of(klass){ |inst| stub(inst).f{ 5 } }
88
88
  obj = klass.new
89
89
  obj.f.should.eq 5
90
90
  spy(any_instance_of(klass)).f.times(2)
91
- begin
92
- Muack.verify
93
- rescue Muack::Expected => e
94
- expected = /Muack::API\.any_instance_of\(.+?\)\.f\(\)/
95
- e.expected .should =~ expected
96
- e.expected_times.should.eq 2
97
- e.actual_times .should.eq 1
98
- end
91
+
92
+ e = should.raise(Muack::Expected){ Muack.verify }
93
+ expected = /Muack::API\.any_instance_of\(.+?\)\.f\(\)/
94
+ e.expected .should =~ expected
95
+ e.expected_times.should.eq 2
96
+ e.actual_times .should.eq 1
97
+
99
98
  obj.f.should.eq 0
100
99
  end
101
100
 
102
- should 'stub with any_instance_of and spy over satisfied' do
101
+ would 'stub with any_instance_of and spy over satisfied' do
103
102
  any_instance_of(klass){ |inst| stub(inst).f{ 2 } }
104
103
  obj = klass.new
105
104
  2.times{ obj.f.should.eq 2 }
106
105
  spy(any_instance_of(klass)).f
107
- begin
108
- Muack.verify
109
- rescue Muack::Expected => e
110
- expected = /Muack::API\.any_instance_of\(.+?\)\.f\(\)/
111
- e.expected .should =~ expected
112
- e.expected_times.should.eq 1
113
- e.actual_times .should.eq 2
114
- end
106
+
107
+ e = should.raise(Muack::Expected){ Muack.verify }
108
+ expected = /Muack::API\.any_instance_of\(.+?\)\.f\(\)/
109
+ e.expected .should =~ expected
110
+ e.expected_times.should.eq 1
111
+ e.actual_times .should.eq 2
112
+
115
113
  obj.f.should.eq 0
116
114
  end
117
115
  end