mocoso 0.0.1

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 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: []