mocoso 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 582dde2452597ff29ecf14f4b3b980ca5d53a02a
4
+ data.tar.gz: c95e557a539ddf097439ac91f4af19c273e1b47e
5
+ SHA512:
6
+ metadata.gz: 0f6f811c7c9a6c057e2d6b517062504ab60a04ea04addf464f73d361c41be07415a781946e330a71730193837c6819c01f82641188c017ae3008a3a69e92c689
7
+ data.tar.gz: 0235d2b34437f476e9e8989512d038c1db485345df46d2cc5bb053df1e6a6f437c743858da28955a200de503d8fb50d3f8d51ef87d59a2d42321eabe86f176ac
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2013 Francesco Rodríguez
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,78 @@
1
+ Mocoso [![Build Status](https://travis-ci.org/frodsan/mocoso.png)](https://travis-ci.org/frodsan/mocoso)
2
+ ======
3
+
4
+ Yet Another Simple Stub & Mock library. This is inspired by tools such as
5
+ [Minitest::Mock][minitest], [Override][override] and [Mocha][mocha].
6
+
7
+ Motivation
8
+ ----------
9
+
10
+ **tl;dr: Il mío capriccio**
11
+
12
+ Yes, there are a lot of good libraries out there, but I wanted one that
13
+ meets the following criteria:
14
+
15
+ * Provides features to restore stubbed methods to their original implementations.
16
+ * Doesn't allow to stub or mock undefined methods.
17
+ * Doesn't monkey-patch any class or object.
18
+ * Test-framework agnostic (Doesn't need integration code).
19
+
20
+ And the most important: simplicity.
21
+
22
+ Installation
23
+ ------------
24
+
25
+ $ gem install mocoso
26
+
27
+ Usage
28
+ -----
29
+
30
+ A quick example (uses [Cutest][cutest]):
31
+
32
+ require 'cutest'
33
+ require 'mocoso'
34
+
35
+ include Mocoso
36
+
37
+ test 'mocking a class method' do
38
+ user = User.new
39
+ expect User, :find, with: [1], return: user
40
+ assert_equal user, User.find(1)
41
+ end
42
+
43
+ test 'stubbing an instance method' do
44
+ user = User.new
45
+ stub user, valid?: true
46
+ assert user.valid?
47
+ end
48
+
49
+ Check [Official Documentation][docs] for more details.
50
+
51
+ License
52
+ -------
53
+
54
+ Copyright (c) 2013 Francesco Rodríguez
55
+
56
+ Permission is hereby granted, free of charge, to any person obtaining a copy
57
+ of this software and associated documentation files (the "Software"), to deal
58
+ in the Software without restriction, including without limitation the rights
59
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
60
+ copies of the Software, and to permit persons to whom the Software is
61
+ furnished to do so, subject to the following conditions:
62
+
63
+ The above copyright notice and this permission notice shall be included in
64
+ all copies or substantial portions of the Software.
65
+
66
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
67
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
68
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
69
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
70
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
71
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
72
+ THE SOFTWARE.
73
+
74
+ [docs]: http://rubydoc.info/github/frodsan/mocoso/
75
+ [cutest]: https://github.com/djanowski/cutest/
76
+ [override]: https://github.com/soveran/override/
77
+ [minitest]: https://github.com/seattlerb/minitest/
78
+ [mocha]: https://github.com/freerange/mocha/
data/lib/mocoso.rb ADDED
@@ -0,0 +1,194 @@
1
+ # Yet Another Simple Stub & Mock library, that also:
2
+ #
3
+ # - Provides features to restore stubbed methods to their original implementations.
4
+ # - Doesn't allow to stub or mock undefined methods.
5
+ # - Doesn't monkey-patch any class or object.
6
+ # - Test-framework agnostic (Doesn't need integration code).
7
+ #
8
+ # == Setup
9
+ #
10
+ # Execute:
11
+ #
12
+ # gem install mocoso
13
+ #
14
+ # == Usage
15
+ #
16
+ # Quick start:
17
+ #
18
+ # require 'cutest'
19
+ # require 'mocoso'
20
+ #
21
+ # include Mocoso
22
+ #
23
+ # test 'mocking a class method' do
24
+ # user = User.new
25
+ # expect User, :find, with: [1], return: user
26
+ # assert_equal user, User.find(1)
27
+ # end
28
+ #
29
+ # test 'stubbing an instance method' do
30
+ # user = User.new
31
+ # stub user, valid?: true
32
+ # assert user.valid?
33
+ # end
34
+ #
35
+ # Note: this example uses the test framework Cutest[1]:
36
+ #
37
+ # Mocoso is inspired in Override[2], Minitest::Mock[3] and Mocha[4].
38
+ #
39
+ # * [1]: https://github.com/djanowski/cutest/
40
+ # * [2]: https://github.com/soveran/override/
41
+ # * [3]: https://github.com/seattlerb/minitest/
42
+ # * [4]: https://github.com/freerange/mocha/
43
+ #
44
+ module Mocoso
45
+ # Raised by #expect when a expectation is not fulfilled.
46
+ #
47
+ # Mocoso.expect object, :method, with: 'argument', returns: nil
48
+ #
49
+ # object.method 'unexpected argument'
50
+ # # => Mocoso::ExpectationError: Expected ["argument"], got ["unexpected argument"]
51
+ #
52
+ ExpectationError = Class.new StandardError
53
+
54
+ # Rewrites each method from `methods` and defined in +object+. `methods` is a
55
+ # Hash that represents stubbed method name symbols as keys and corresponding
56
+ # return values as values.
57
+ #
58
+ # signup = SignupForm.new params[:user]
59
+ #
60
+ # signup.valid? # => false
61
+ # signup.save # => false
62
+ #
63
+ # Mocoso.stub signup, valid?: true, signup: true
64
+ #
65
+ # signup.valid? # => true
66
+ # signup.save # => true
67
+ #
68
+ # You can pass a callable object (responds to +call+) as a value:
69
+ #
70
+ # Mocoso.stub subject, foo: -> { "foo" }, bar: ->(value) { value }
71
+ #
72
+ # subject.foo # => "foo"
73
+ # subject.bar('foo') # => "foo"
74
+ #
75
+ # If you try to stub a method that is not defined by the +object+,
76
+ # it raises an error.
77
+ #
78
+ # Mocoso.stub Object.new, undefined: nil
79
+ # # => NameError: undefined method `undefined' for class `Object'
80
+ #
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
96
+ metaclass = object.singleton_class
97
+
98
+ methods.each do |method, result|
99
+ metaclass.send :alias_method, stub_method_name(method), method
100
+ metaclass.send :define_method, method do |*args|
101
+ result.respond_to?(:call) ? result.call(*args) : result
102
+ end
103
+ end
104
+
105
+ if block_given?
106
+ begin
107
+ yield
108
+ ensure
109
+ unstub object, methods.keys
110
+ end
111
+ end
112
+ end
113
+
114
+ # Removes the specified stubbed +methods+ (added by calls to #stub or #expect) and
115
+ # restores the original behaviour of the methods before they were stubbed.
116
+ #
117
+ # object.foo # => "foo"
118
+ #
119
+ # Mocoso.stub object, foo: 'new foo'
120
+ # object.foo # => "new foo"
121
+ #
122
+ # Mocoso.unstub object, [:foo]
123
+ # object.foo #=> "foo"
124
+ #
125
+ # I personally use a block on #stub or #expect to avoid side effects, because if
126
+ # you #unstub a method which still has unsatisfied expectations, you may be
127
+ # removing the only way those expectations can be satisfied. Use it on your
128
+ # own responsibility.
129
+ #
130
+ # This method was born as a helper for #stub.
131
+ #
132
+ def unstub object, methods
133
+ metaclass = object.singleton_class
134
+
135
+ methods.each do |method|
136
+ metaclass.send :undef_method, method
137
+ metaclass.send :alias_method, method, stub_method_name(method)
138
+ metaclass.send :undef_method, stub_method_name(method)
139
+ end
140
+ end
141
+
142
+ def stub_method_name name
143
+ "__mocoso_#{name}"
144
+ end
145
+ private :stub_method_name
146
+
147
+ # Expect that method +method+ is called with the arguments specified in the
148
+ # +:with+ option (defaults to +[]+ if it's not given) and returns the value
149
+ # specified in the +:return+ option. If expectations are not met, it raises
150
+ # Mocoso::ExpectationError error.
151
+ #
152
+ # class User < Model
153
+ # end
154
+ #
155
+ # user = User[1]
156
+ #
157
+ # Mocoso.expect user, :update, with: [{ name: 'new name' }], returns: true
158
+ #
159
+ # subject.update unexpected: nil
160
+ # # => Mocoso::ExpectationError: Expected [{:name=>"new name"}], got [{:unexpected=>nil}]
161
+ #
162
+ # user.update name: 'new name'
163
+ # # => true
164
+ #
165
+ # Note that it will rewrite the method in +object+. If you want to set an
166
+ # expectation without side effects, you should pass a block.
167
+ #
168
+ # User.exists? 1
169
+ # # => false
170
+ #
171
+ # Mocoso.expect User, :exists?, with: [1], returns: true do
172
+ # User.exists? 1
173
+ # # => true
174
+ # end
175
+ #
176
+ # User.exists? 1
177
+ # # => false
178
+ #
179
+ def expect object, method, options
180
+ expectation = -> *params {
181
+ with = options.fetch(:with) { [] }
182
+
183
+ raise ExpectationError, "Expected #{with}, got #{params}" if params != with
184
+
185
+ options[:return]
186
+ }
187
+
188
+ if block_given?
189
+ stub object, method => expectation, &proc
190
+ else
191
+ stub object, method => expectation
192
+ end
193
+ end
194
+ end
data/mocoso.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'mocoso'
5
+ s.version = '0.0.1'
6
+ s.summary = 'A simple stub & mock library'
7
+ s.description = s.summary
8
+ s.authors = ['Francesco Rodríguez']
9
+ s.email = ['lrodriguezsanc@gmail.com']
10
+ s.homepage = 'https://github.com/frodsan/mocoso'
11
+ s.license = 'MIT'
12
+
13
+ s.files = Dir[
14
+ 'LICENSE',
15
+ 'README.md',
16
+ 'lib/**/*.rb',
17
+ '*.gemspec',
18
+ 'test/*.*'
19
+ ]
20
+
21
+ s.add_development_dependency 'cutest'
22
+ end
@@ -0,0 +1,119 @@
1
+ require 'cutest'
2
+ require_relative '../lib/mocoso'
3
+
4
+ class Subject
5
+ def foo; 'foo'; end
6
+ def bar; 'bar'; end
7
+ def baz(value); value; end
8
+
9
+ def self.foo
10
+ 'foo'
11
+ end
12
+ end
13
+
14
+ include Mocoso
15
+
16
+ setup do
17
+ Subject.new
18
+ end
19
+
20
+ test 'raises error if object not respond to the given method' do |subject|
21
+ assert_raise { stub(subject, nan: nil, undefined: nil) }
22
+ end
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
32
+ end
33
+
34
+ test 'stubs method with a callable object' do |subject|
35
+ before = subject.foo
36
+
37
+ stub subject, foo: -> { 'new foo' }
38
+
39
+ assert subject.foo != before
40
+ assert subject.foo == 'new foo'
41
+ end
42
+
43
+ test 'stubs method with a callable object with arguments' do |subject|
44
+ before = subject.foo
45
+
46
+ stub subject, foo: ->(a) { "new #{a}" }
47
+
48
+ assert subject.foo('foo') != before
49
+ end
50
+
51
+ test 'stubs method without side effects if a block is given' do
52
+ before = Subject.foo
53
+
54
+ stub Subject, foo: 'new foo' do
55
+ assert before != Subject.foo
56
+ end
57
+
58
+ assert_equal before, Subject.foo
59
+ end
60
+
61
+ test 'succeeds if expectations are met' do |subject|
62
+ expect subject, :baz, with: ['value'], return: 'result'
63
+
64
+ assert_equal 'result', subject.baz('value')
65
+ end
66
+
67
+ test 'raises an error if expectation are not met' do |subject|
68
+ expect subject, :baz, with: ['value'], return: 'result'
69
+
70
+ assert_raise(Mocoso::ExpectationError) { subject.baz('another') }
71
+ end
72
+
73
+ test 'expectation without side effects if a block is given' do |subject|
74
+ expect subject, :baz, with: ['value'], return: 'mocked' do
75
+ assert_equal 'mocked', subject.baz('value')
76
+ end
77
+
78
+ assert_equal 'original', subject.baz('original')
79
+ end
80
+
81
+ test 'expectation without arguments' do |subject|
82
+ expect subject, :foo, return: 'new foo'
83
+
84
+ assert_equal 'new foo', subject.foo
85
+ end
86
+
87
+ test 'expectation with multiple arguments' do |subject|
88
+ expect subject, :foo, with: ['new foo', { optional: true }], return: 'new foo'
89
+
90
+ assert_equal 'new foo', subject.foo('new foo', optional: true)
91
+ end
92
+
93
+ test 'unstub removes specified stubbed methods' do |subject|
94
+ before_foo = subject.foo
95
+ before_bar = subject.bar
96
+
97
+ stub subject, foo: 'new foo', bar: 'new bar', baz: 'new baz'
98
+
99
+ assert before_foo != subject.foo
100
+ assert before_bar != subject.bar
101
+
102
+ unstub subject, [:foo, :bar]
103
+
104
+ assert_equal before_foo, subject.foo
105
+ assert_equal before_bar, subject.bar
106
+ assert_equal 'new baz', subject.baz
107
+ end
108
+
109
+ test 'unstub removes specified expectations' do
110
+ before = Subject.foo
111
+
112
+ expect Subject, :foo, return: 'new foo'
113
+
114
+ assert_equal 'new foo', Subject.foo
115
+
116
+ unstub Subject, [:foo]
117
+
118
+ assert_equal before, Subject.foo
119
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mocoso
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Francesco Rodríguez
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cutest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: A simple stub & mock library
28
+ email:
29
+ - lrodriguezsanc@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - LICENSE
35
+ - README.md
36
+ - lib/mocoso.rb
37
+ - mocoso.gemspec
38
+ - test/scary_mocks_and_nice_stubs.rb
39
+ homepage: https://github.com/frodsan/mocoso
40
+ licenses:
41
+ - MIT
42
+ metadata: {}
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 2.2.0.preview.1
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: A simple stub & mock library
63
+ test_files: []