mocoso 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c12b98f62eb01e570daf1a9101b16a168837ec7d
4
- data.tar.gz: cafcefb94d91446ff97bfb0e8ab72883be345101
3
+ metadata.gz: e5c21876105f80fb7e2c5f0f72b09406e83be714
4
+ data.tar.gz: af2c896fb182aa84454381aaa4060b3a04245078
5
5
  SHA512:
6
- metadata.gz: af1706795d43d65d19045663aee87eaf42448ef47c6a1147193282bf522000be8dfccb1800bd852c0bb5e09451dbab42d968ca943ba749c70354ca88a19a96f2
7
- data.tar.gz: 1a2aeaea3ae9b6f2b86a7c922c353c9c4173ffb00638c506921f7715ceba1315b5fac551241097175a15a9738a99a8b851dc04748e5f30cdf0854b451c32a686
6
+ metadata.gz: a5e18f8f38ba523988872a90be55bd2a3d0685258741fb13e238657c612c48c7fedbb1a2e9fa032f100b1ecb1d0385c817d62cfa7ad4b5b3b83c0ebf8960a402
7
+ data.tar.gz: 5f717db7f95cf129560e2e2c2f40b710d88860593e240d9d9afba63ee1fe99b5ac90ee8138f2edf3907933b2b7a5352c1332be6875527537c48227b9c908132f
data/README.md CHANGED
@@ -12,7 +12,7 @@ Motivation
12
12
  Yes, there are a lot of good libraries out there, but I wanted one that
13
13
  meets the following criteria:
14
14
 
15
- * Provides features to restore stubbed methods to their original implementations.
15
+ * Always restore stubbed methods to their original implementations.
16
16
  * Doesn't allow to stub or mock undefined methods.
17
17
  * Doesn't monkey-patch any class or object.
18
18
  * Test-framework agnostic (Doesn't need integration code).
@@ -36,14 +36,18 @@ A quick example (uses [Cutest][cutest]):
36
36
 
37
37
  test 'mocking a class method' do
38
38
  user = User.new
39
- expect User, :find, with: [1], return: user
40
- assert_equal user, User.find(1)
39
+
40
+ expect User, :find, with: [1], return: user do
41
+ assert_equal user, User.find(1)
42
+ end
41
43
  end
42
44
 
43
45
  test 'stubbing an instance method' do
44
46
  user = User.new
45
- stub user, valid?: true
46
- assert user.valid?
47
+
48
+ stub user, valid?: true do
49
+ assert user.valid?
50
+ end
47
51
  end
48
52
 
49
53
  Check [Official Documentation][docs] for more details.
data/lib/mocoso.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # Yet Another Simple Stub & Mock library, that also:
2
2
  #
3
- # - Provides features to restore stubbed methods to their original implementations.
3
+ # - Always restore stubbed methods to their original implementations.
4
4
  # - Doesn't allow to stub or mock undefined methods.
5
5
  # - Doesn't monkey-patch any class or object.
6
6
  # - Test-framework agnostic (Doesn't need integration code).
@@ -22,14 +22,18 @@
22
22
  #
23
23
  # test 'mocking a class method' do
24
24
  # user = User.new
25
- # expect User, :find, with: [1], return: user
26
- # assert_equal user, User.find(1)
25
+ #
26
+ # expect User, :find, with: [1], return: user do
27
+ # assert_equal user, User.find(1)
28
+ # end
27
29
  # end
28
30
  #
29
31
  # test 'stubbing an instance method' do
30
32
  # user = User.new
31
- # stub user, valid?: true
32
- # assert user.valid?
33
+ #
34
+ # stub user, valid?: true do
35
+ # assert user.valid?
36
+ # end
33
37
  # end
34
38
  #
35
39
  # Note: this example uses the test framework Cutest[1]:
@@ -44,33 +48,35 @@
44
48
  module Mocoso
45
49
  # Raised by #expect when a expectation is not fulfilled.
46
50
  #
47
- # Mocoso.expect object, :method, with: 'argument', returns: nil
48
- #
49
- # object.method 'unexpected argument'
50
- # # => Mocoso::ExpectationError: Expected ["argument"], got ["unexpected argument"]
51
+ # Mocoso.expect object, :method, with: 'argument', returns: nil do
52
+ # object.method 'unexpected argument'
53
+ # # => Mocoso::ExpectationError: Expected ["argument"], got ["unexpected argument"]
54
+ # end
51
55
  #
52
56
  ExpectationError = Class.new StandardError
53
57
 
54
- # Rewrites each method from `methods` and defined in +object+. `methods` is a
58
+ # Rewrites each method from +methods+ and defined in +object+. +methods+ is a
55
59
  # Hash that represents stubbed method name symbols as keys and corresponding
56
- # return values as values.
60
+ # return values as values. The methods are restored after the given +block+
61
+ # is executed.
57
62
  #
58
63
  # signup = SignupForm.new params[:user]
59
64
  #
60
65
  # signup.valid? # => false
61
- # signup.save # => false
62
- #
63
- # Mocoso.stub signup, valid?: true, signup: true
64
66
  #
65
- # signup.valid? # => true
66
- # signup.save # => true
67
+ # Mocoso.stub signup, :valid?, true do
68
+ # signup.valid? # => true
69
+ # end
67
70
  #
68
71
  # You can pass a callable object (responds to +call+) as a value:
69
72
  #
70
- # Mocoso.stub subject, foo: -> { "foo" }, bar: ->(value) { value }
73
+ # Mocoso.stub subject, foo: -> { "foo" } do
74
+ # subject.foo # => "foo"
75
+ # end
71
76
  #
72
- # subject.foo # => "foo"
73
- # subject.bar('foo') # => "foo"
77
+ # Mocoso.stub subject, :bar, ->(value) { value } do
78
+ # subject.bar('foo') # => "foo"
79
+ # end
74
80
  #
75
81
  # If you try to stub a method that is not defined by the +object+,
76
82
  # it raises an error.
@@ -78,79 +84,32 @@ module Mocoso
78
84
  # Mocoso.stub Object.new, undefined: nil
79
85
  # # => NameError: undefined method `undefined' for class `Object'
80
86
  #
81
- # Note that it will rewrite the method(s) in +object+. If you want to stub a
82
- # method without side effects, you should pass a block.
83
- #
84
- # User.all.length
85
- # # => 5
86
- #
87
- # Mocoso.stub User, all: [] do
88
- # User.all.length
89
- # # => 0
90
- # end
91
- #
92
- # User.all.length
93
- # # => 5
94
- #
95
- def stub object, methods
87
+ def stub object, method, result, &block
96
88
  metaclass = object.singleton_class
89
+ stubbed_method = "__mocoso_#{method}"
97
90
 
98
- methods.each do |method, result|
99
- metaclass.send :alias_method, stub_method_name(method), method
91
+ metaclass.send :alias_method, stubbed_method, method
100
92
 
101
- if result.respond_to?(:call)
102
- metaclass.send(:define_method, method) { |*args| result.call(*args) }
103
- else
104
- metaclass.send(:define_method, method) { result }
105
- end
106
- end
107
-
108
- if block_given?
109
- begin
110
- yield
111
- ensure
112
- unstub object, methods.keys
113
- end
93
+ if result.respond_to?(:call)
94
+ metaclass.send(:define_method, method) { |*args| result.(*args) }
95
+ else
96
+ metaclass.send(:define_method, method) { result }
114
97
  end
115
- end
116
-
117
- # Removes the specified stubbed +methods+ (added by calls to #stub or #expect) and
118
- # restores the original behaviour of the methods before they were stubbed.
119
- #
120
- # object.foo # => "foo"
121
- #
122
- # Mocoso.stub object, foo: 'new foo'
123
- # object.foo # => "new foo"
124
- #
125
- # Mocoso.unstub object, [:foo]
126
- # object.foo #=> "foo"
127
- #
128
- # I personally use a block on #stub or #expect to avoid side effects, because if
129
- # you #unstub a method which still has unsatisfied expectations, you may be
130
- # removing the only way those expectations can be satisfied. Use it on your
131
- # own responsibility.
132
- #
133
- # This method was born as a helper for #stub.
134
- #
135
- def unstub object, methods
136
- metaclass = object.singleton_class
137
98
 
138
- methods.each do |method|
99
+ begin
100
+ yield
101
+ ensure
139
102
  metaclass.send :undef_method, method
140
- metaclass.send :alias_method, method, stub_method_name(method)
141
- metaclass.send :undef_method, stub_method_name(method)
103
+ metaclass.send :alias_method, method, stubbed_method
104
+ metaclass.send :undef_method, stubbed_method
142
105
  end
143
106
  end
144
107
 
145
- def stub_method_name name
146
- "__mocoso_#{name}"
147
- end
148
- private :stub_method_name
149
-
150
108
  # Expect that method +method+ is called with the arguments specified in the
151
109
  # +:with+ option (defaults to +[]+ if it's not given) and returns the value
152
- # specified in the +:return+ option. If expectations are not met, it raises
153
- # Mocoso::ExpectationError error.
110
+ # specified in the +:returns+ option. If expectations are not met, it raises
111
+ # Mocoso::ExpectationError error. It uses #stub internally, so it will restore
112
+ # the methods to their original implementation after the +block+ is executed.
154
113
  #
155
114
  # class User < Model
156
115
  # end
@@ -158,40 +117,19 @@ module Mocoso
158
117
  # user = User[1]
159
118
  #
160
119
  # Mocoso.expect user, :update, with: [{ name: 'new name' }], returns: true
120
+ # subject.update unexpected: nil
121
+ # # => Mocoso::ExpectationError: Expected [{:name=>"new name"}], got [{:unexpected=>nil}]
161
122
  #
162
- # subject.update unexpected: nil
163
- # # => Mocoso::ExpectationError: Expected [{:name=>"new name"}], got [{:unexpected=>nil}]
164
- #
165
- # user.update name: 'new name'
166
- # # => true
167
- #
168
- # Note that it will rewrite the method in +object+. If you want to set an
169
- # expectation without side effects, you should pass a block.
170
- #
171
- # User.exists? 1
172
- # # => false
173
- #
174
- # Mocoso.expect User, :exists?, with: [1], returns: true do
175
- # User.exists? 1
123
+ # user.update name: 'new name'
176
124
  # # => true
177
125
  # end
178
126
  #
179
- # User.exists? 1
180
- # # => false
181
- #
182
- def expect object, method, options
127
+ def expect object, method, with: [], returns:, &block
183
128
  expectation = -> *params {
184
- with = options.fetch(:with) { [] }
185
-
186
129
  raise ExpectationError, "Expected #{with}, got #{params}" if params != with
187
-
188
- options[:return]
130
+ returns
189
131
  }
190
132
 
191
- if block_given?
192
- stub object, method => expectation, &proc
193
- else
194
- stub object, method => expectation
195
- end
133
+ stub object, method, expectation, &block
196
134
  end
197
135
  end
data/mocoso.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'mocoso'
5
- s.version = '0.0.2'
5
+ s.version = '0.1.0'
6
6
  s.summary = 'A simple stub & mock library'
7
7
  s.description = s.summary
8
8
  s.authors = ['Francesco Rodríguez']
@@ -17,104 +17,66 @@ setup do
17
17
  Subject.new
18
18
  end
19
19
 
20
- test 'raises error if object not respond to the given method' do |subject|
21
- assert_raise { stub(subject, nan: nil, undefined: nil) }
20
+ test 'raises error if block is not given' do |subject|
21
+ assert_raise { stub(subject, foo: 'foo') }
22
22
  end
23
23
 
24
- test 'stubs methods and return new values' do |subject|
25
- before_foo = subject.foo
26
- before_bar = subject.bar
27
-
28
- stub subject, foo: 'new foo', bar: 'new bar'
29
-
30
- assert subject.foo != before_foo
31
- assert subject.bar != before_bar
24
+ test 'raises error if object not respond to the given method' do |subject|
25
+ assert_raise(NameError) { stub(subject, :nan, nil) }
32
26
  end
33
27
 
34
- test 'stubs method with a callable object' do |subject|
28
+ test 'stubbed method return new value' do |subject|
35
29
  before = subject.foo
36
30
 
37
- stub subject, foo: -> { 'new foo' }
31
+ stub subject, :foo, 'new foo' do
32
+ assert_equal 'new foo', subject.foo
33
+ end
38
34
 
39
- assert subject.foo != before
40
- assert_equal 'new foo', subject.foo
35
+ assert_equal before, subject.foo
41
36
  end
42
37
 
43
- test 'stubs method with a callable object with arguments' do |subject|
38
+ test 'stubs method with a callable object' do |subject|
44
39
  before = subject.foo
45
40
 
46
- stub subject, foo: ->(a) { "new #{a}" }
41
+ stub subject, :foo, -> { 'new foo' } do
42
+ assert_equal 'new foo', subject.foo
43
+ end
47
44
 
48
- assert subject.foo('foo') != before
49
- assert_equal 'new foo', subject.foo('foo')
45
+ assert_equal before, subject.foo
50
46
  end
51
47
 
52
- test 'stubs method without side effects if a block is given' do
53
- before = Subject.foo
48
+ test 'stubs method with a callable object that requires arguments' do |subject|
49
+ before = subject.foo
54
50
 
55
- stub Subject, foo: 'new foo' do
56
- assert before != Subject.foo
51
+ stub subject, :foo, ->(a) { "new #{a}" } do
52
+ assert_equal 'new foo', subject.foo('foo')
57
53
  end
58
54
 
59
- assert_equal before, Subject.foo
55
+ assert_equal before, subject.foo
60
56
  end
61
57
 
62
58
  test 'succeeds if expectations are met' do |subject|
63
- expect subject, :baz, with: ['value'], return: 'result'
59
+ expect subject, :baz, with: ['value'], returns: 'result' do
60
+ assert_equal 'result', subject.baz('value')
61
+ end
64
62
 
65
- assert_equal 'result', subject.baz('value')
63
+ assert_equal 'baz', subject.baz('baz')
66
64
  end
67
65
 
68
66
  test 'raises an error if expectation are not met' do |subject|
69
- expect subject, :baz, with: ['value'], return: 'result'
70
-
71
- assert_raise(Mocoso::ExpectationError) { subject.baz('another') }
72
- end
73
-
74
- test 'expectation without side effects if a block is given' do |subject|
75
- expect subject, :baz, with: ['value'], return: 'mocked' do
76
- assert_equal 'mocked', subject.baz('value')
67
+ expect subject, :baz, with: ['value'], returns: 'result' do
68
+ assert_raise(Mocoso::ExpectationError) { subject.baz('another') }
77
69
  end
78
-
79
- assert_equal 'original', subject.baz('original')
80
70
  end
81
71
 
82
- test 'expectation without arguments' do |subject|
83
- expect subject, :foo, return: 'new foo'
84
-
85
- assert_equal 'new foo', subject.foo
72
+ test 'expectation without with option defaults to empty array' do |subject|
73
+ expect subject, :foo, returns: 'new foo' do
74
+ assert_equal 'new foo', subject.foo
75
+ end
86
76
  end
87
77
 
88
78
  test 'expectation with multiple arguments' do |subject|
89
- expect subject, :foo, with: ['new foo', { optional: true }], return: 'new foo'
90
-
91
- assert_equal 'new foo', subject.foo('new foo', optional: true)
92
- end
93
-
94
- test 'unstub removes specified stubbed methods' do |subject|
95
- before_foo = subject.foo
96
- before_bar = subject.bar
97
-
98
- stub subject, foo: 'new foo', bar: 'new bar', baz: 'new baz'
99
-
100
- assert before_foo != subject.foo
101
- assert before_bar != subject.bar
102
-
103
- unstub subject, [:foo, :bar]
104
-
105
- assert_equal before_foo, subject.foo
106
- assert_equal before_bar, subject.bar
107
- assert_equal 'new baz', subject.baz
108
- end
109
-
110
- test 'unstub removes specified expectations' do
111
- before = Subject.foo
112
-
113
- expect Subject, :foo, return: 'new foo'
114
-
115
- assert_equal 'new foo', Subject.foo
116
-
117
- unstub Subject, [:foo]
118
-
119
- assert_equal before, Subject.foo
79
+ expect subject, :foo, with: ['new foo', { optional: true }], returns: 'new foo' do
80
+ assert_equal 'new foo', subject.foo('new foo', optional: true)
81
+ end
120
82
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mocoso
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Francesco Rodríguez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-03 00:00:00.000000000 Z
11
+ date: 2013-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cutest