bogus 0.0.1 → 0.0.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.
- data/.travis.yml +0 -1
- data/CHANGELOG.md +17 -0
- data/Gemfile.lock +1 -1
- data/features/anonymous_doubles.feature +129 -0
- data/features/step_definitions/rspec_steps.rb +0 -2
- data/lib/bogus.rb +8 -30
- data/lib/bogus/creates_anonymous_stubs.rb +27 -0
- data/lib/bogus/method_stringifier.rb +12 -0
- data/lib/bogus/public_methods.rb +10 -6
- data/lib/bogus/rspec.rb +2 -0
- data/lib/bogus/rspec_extensions.rb +10 -6
- data/lib/bogus/verifies_stub_definition.rb +1 -0
- data/lib/bogus/version.rb +1 -1
- data/spec/bogus/copies_classes_spec.rb +14 -0
- data/spec/bogus/mocking_dsl_spec.rb +40 -0
- data/spec/bogus/verifies_stub_definition_spec.rb +23 -0
- metadata +7 -4
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## 0.0.1
|
4
|
+
|
5
|
+
Initial version.
|
6
|
+
|
7
|
+
- Fakes.
|
8
|
+
- Safe spying, stubbing, mocking.
|
9
|
+
- Veryfying contracts defined by test doubles.
|
10
|
+
|
11
|
+
## 0.0.2
|
12
|
+
|
13
|
+
- Makes it possible to stub method calls on objects that utilize method missing.
|
14
|
+
- Removed the need to require both bogus and bogus/rspec.
|
15
|
+
- Implemented anonymous fakes.
|
16
|
+
- Fixed a bug in copying ActiveRecord classes.
|
17
|
+
- (internal) Replaced autoloads with require.
|
data/Gemfile.lock
CHANGED
@@ -0,0 +1,129 @@
|
|
1
|
+
Feature: Anonymous test doubles
|
2
|
+
|
3
|
+
Anonymous test doubles can be useful as a stepping stone towards
|
4
|
+
actual fakes and when migrating from another testing library.
|
5
|
+
|
6
|
+
In contrast with other testing libraries, Bogus makes it's fakes
|
7
|
+
respond to all methods by default and makes those calls chainable.
|
8
|
+
This way you can spy on methods without stubbing them first.
|
9
|
+
|
10
|
+
It is not advisable to use those for anything else than an intermediate step.
|
11
|
+
Fakes that mimic an actual class have many more benefits.
|
12
|
+
|
13
|
+
Background:
|
14
|
+
Given a file named "foo.rb" with:
|
15
|
+
"""ruby
|
16
|
+
class Student
|
17
|
+
attr_reader :library_card
|
18
|
+
|
19
|
+
def initialize(name)
|
20
|
+
@name = name
|
21
|
+
end
|
22
|
+
|
23
|
+
def sign_up(library)
|
24
|
+
@library_card = library.register_junior(@name)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
"""
|
28
|
+
|
29
|
+
Scenario: Stubbing any method with any parameters
|
30
|
+
Then spec file with following content should pass:
|
31
|
+
"""ruby
|
32
|
+
describe Student do
|
33
|
+
let(:library) { fake }
|
34
|
+
let(:jake) { Student.new("Jake") }
|
35
|
+
|
36
|
+
it "allows stubbing any method with any parameters" do
|
37
|
+
stub(library).register_junior { "the card" }
|
38
|
+
|
39
|
+
jake.sign_up(library)
|
40
|
+
|
41
|
+
jake.library_card.should == "the card"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
"""
|
45
|
+
|
46
|
+
Scenario: Stubbing methods in initializer
|
47
|
+
Then spec file with following content should pass:
|
48
|
+
"""ruby
|
49
|
+
describe Student do
|
50
|
+
let(:library) { fake(register_junior: "the card") }
|
51
|
+
let(:jake) { Student.new("Jake") }
|
52
|
+
|
53
|
+
it "allows stubbing any method with any parameters" do
|
54
|
+
jake.sign_up(library)
|
55
|
+
|
56
|
+
jake.library_card.should == "the card"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
"""
|
60
|
+
|
61
|
+
Scenario: Mocking any method with any parameters
|
62
|
+
Then spec file with following content should pass:
|
63
|
+
"""ruby
|
64
|
+
describe Student do
|
65
|
+
let(:library) { fake }
|
66
|
+
let(:jake) { Student.new("Jake") }
|
67
|
+
|
68
|
+
it "allows stubbing any method with any parameters" do
|
69
|
+
mock(library).register_junior("Jake") { "the card" }
|
70
|
+
|
71
|
+
jake.sign_up(library)
|
72
|
+
|
73
|
+
jake.library_card.should == "the card"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
"""
|
77
|
+
|
78
|
+
Scenario: Mocking any method with any parameters
|
79
|
+
Then spec file with following content should fail:
|
80
|
+
"""ruby
|
81
|
+
describe Student do
|
82
|
+
it "allows stubbing any method with any parameters" do
|
83
|
+
library = fake
|
84
|
+
mock(library).register_junior { "the card" }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
"""
|
88
|
+
|
89
|
+
Scenario: Stubbing methods in initializer
|
90
|
+
Then spec file with following content should pass:
|
91
|
+
"""ruby
|
92
|
+
describe Student do
|
93
|
+
let(:library) { fake(register_junior: "the card") }
|
94
|
+
let(:jake) { Student.new("Jake") }
|
95
|
+
|
96
|
+
it "allows stubbing any method with any parameters" do
|
97
|
+
jake.sign_up(library)
|
98
|
+
|
99
|
+
jake.library_card.should == "the card"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
"""
|
103
|
+
|
104
|
+
Scenario: Spying on method calls
|
105
|
+
Then spec file with following content should pass:
|
106
|
+
"""ruby
|
107
|
+
describe Student do
|
108
|
+
let(:library) { fake }
|
109
|
+
let(:jake) { Student.new("Jake") }
|
110
|
+
|
111
|
+
it "allows stubbing any method with any parameters" do
|
112
|
+
jake.sign_up(library)
|
113
|
+
|
114
|
+
library.should have_received.register_junior("Jake")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
"""
|
118
|
+
|
119
|
+
Scenario: Invoking arbitrary methods
|
120
|
+
Then spec file with following content should pass:
|
121
|
+
"""ruby
|
122
|
+
describe Student do
|
123
|
+
let(:library) { fake }
|
124
|
+
|
125
|
+
it "allows stubbing any method with any parameters" do
|
126
|
+
library.foo.bar("hello").baz.should == library
|
127
|
+
end
|
128
|
+
end
|
129
|
+
"""
|
data/lib/bogus.rb
CHANGED
@@ -1,35 +1,13 @@
|
|
1
1
|
require 'dependor'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
autoload :Double, 'bogus/double'
|
11
|
-
autoload :Fake, 'bogus/fake'
|
12
|
-
autoload :FakeRegistry, 'bogus/fake_registry'
|
13
|
-
autoload :Injector, 'bogus/injector'
|
14
|
-
autoload :Interaction, 'bogus/interaction'
|
15
|
-
autoload :InteractionPresenter, 'bogus/interaction_presenter'
|
16
|
-
autoload :InteractionsRepository, 'bogus/interactions_repository'
|
17
|
-
autoload :InvocationMatcher, 'bogus/invocation_matcher'
|
18
|
-
autoload :MethodStringifier, 'bogus/method_stringifier'
|
19
|
-
autoload :MockingDSL, 'bogus/rspec_extensions'
|
20
|
-
autoload :OverwritesClasses, 'bogus/overwrites_classes'
|
21
|
-
autoload :ProxyClass, 'bogus/proxy_class'
|
22
|
-
autoload :PublicMethods, 'bogus/public_methods'
|
23
|
-
autoload :RRProxy, 'bogus/rr_proxy'
|
24
|
-
autoload :RSpecExtensions, 'bogus/rspec_extensions'
|
25
|
-
autoload :RecordInteractions, 'bogus/record_interactions'
|
26
|
-
autoload :RecordingProxy, 'bogus/recording_proxy'
|
27
|
-
autoload :RecordsDoubleInteractions, 'bogus/records_double_interactions'
|
28
|
-
autoload :RegistersCreatedFakes, 'bogus/registers_created_fakes'
|
29
|
-
autoload :Takes, 'bogus/takes'
|
30
|
-
autoload :VERSION, 'bogus/version'
|
31
|
-
autoload :VerifiesContracts, 'bogus/verifies_contracts'
|
32
|
-
autoload :VerifiesStubDefinition, 'bogus/verifies_stub_definition'
|
3
|
+
require_relative 'bogus/takes'
|
4
|
+
require_relative 'bogus/record_interactions'
|
5
|
+
require_relative 'bogus/rspec_extensions'
|
6
|
+
|
7
|
+
all_files = Dir[File.expand_path('../**/*.rb', __FILE__)]
|
8
|
+
all_files = all_files.reject{|f| f.include?('bogus/rspec') }.sort
|
9
|
+
all_files.each { |f| require f }
|
33
10
|
|
11
|
+
module Bogus
|
34
12
|
extend PublicMethods
|
35
13
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Bogus
|
2
|
+
class CreatesAnonymousStubs
|
3
|
+
extend Bogus::Takes
|
4
|
+
|
5
|
+
takes :creates_fakes, :create_stub
|
6
|
+
|
7
|
+
def create(methods = {})
|
8
|
+
object = RespondsToEverything.new
|
9
|
+
methods.each do |name, result|
|
10
|
+
create_stub.call(object).__send__(name) { result }
|
11
|
+
end
|
12
|
+
object
|
13
|
+
end
|
14
|
+
|
15
|
+
class RespondsToEverything
|
16
|
+
include RecordInteractions
|
17
|
+
|
18
|
+
def respond_to?(method)
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing(name, *args, &block)
|
23
|
+
__record__(name, *args, &block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -10,6 +10,7 @@ module Bogus
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def arguments_as_string(arguments)
|
13
|
+
arguments = fill_in_missing_names(arguments)
|
13
14
|
arguments.map{|type, name| argument_to_string(name, type) }.compact.join(', ')
|
14
15
|
end
|
15
16
|
|
@@ -27,5 +28,16 @@ module Bogus
|
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
31
|
+
def fill_in_missing_names(arguments)
|
32
|
+
noname_count = 0
|
33
|
+
arguments.map do |type, name|
|
34
|
+
unless name
|
35
|
+
name = "_noname_#{noname_count}"
|
36
|
+
noname_count += 1
|
37
|
+
end
|
38
|
+
[type, name]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
30
42
|
end
|
31
43
|
end
|
data/lib/bogus/public_methods.rb
CHANGED
@@ -25,16 +25,20 @@ module Bogus
|
|
25
25
|
@injector = Bogus::Injector.new
|
26
26
|
end
|
27
27
|
|
28
|
-
def create_stub(
|
29
|
-
inject.create_stub(
|
28
|
+
def create_stub(*args)
|
29
|
+
inject.create_stub(*args)
|
30
30
|
end
|
31
31
|
|
32
|
-
def create_mock(
|
33
|
-
inject.create_mock(
|
32
|
+
def create_mock(*args)
|
33
|
+
inject.create_mock(*args)
|
34
34
|
end
|
35
35
|
|
36
|
-
def have_received(
|
37
|
-
inject.invocation_matcher(
|
36
|
+
def have_received(*args)
|
37
|
+
inject.invocation_matcher(*args)
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_anonymous_stub(*args)
|
41
|
+
inject.creates_anonymous_stubs.create(*args)
|
38
42
|
end
|
39
43
|
|
40
44
|
private
|
data/lib/bogus/rspec.rb
CHANGED
@@ -16,16 +16,20 @@ module Bogus
|
|
16
16
|
end
|
17
17
|
|
18
18
|
module MockingDSL
|
19
|
-
def
|
20
|
-
Bogus.
|
19
|
+
def fake(*args)
|
20
|
+
Bogus.create_anonymous_stub(*args)
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
Bogus.
|
23
|
+
def stub(*args)
|
24
|
+
Bogus.create_stub(*args)
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
Bogus.
|
27
|
+
def have_received(*args)
|
28
|
+
Bogus.have_received(*args)
|
29
|
+
end
|
30
|
+
|
31
|
+
def mock(*args)
|
32
|
+
Bogus.create_mock(*args)
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
@@ -5,6 +5,7 @@ class Bogus::VerifiesStubDefinition
|
|
5
5
|
|
6
6
|
def verify!(object, method_name, args)
|
7
7
|
stubbing_non_existent_method!(object, method_name) unless object.respond_to?(method_name)
|
8
|
+
return unless object.methods.include?(method_name)
|
8
9
|
method = object.method(method_name)
|
9
10
|
wrong_number_of_arguments!(method, args) if under_number_of_required_arguments?(method, args.size)
|
10
11
|
wrong_number_of_arguments!(method, args) if over_number_of_allowed_arguments?(method, args.size)
|
data/lib/bogus/version.rb
CHANGED
@@ -171,5 +171,19 @@ describe Bogus::CopiesClasses do
|
|
171
171
|
|
172
172
|
include_examples 'spying'
|
173
173
|
end
|
174
|
+
|
175
|
+
class SomeModel
|
176
|
+
def save(*)
|
177
|
+
# ignores arguments
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
context "copying classes with methods with nameless parameters" do
|
182
|
+
let(:klass) { SomeModel }
|
183
|
+
|
184
|
+
it "copies those methods" do
|
185
|
+
fake.should respond_to(:save)
|
186
|
+
end
|
187
|
+
end
|
174
188
|
end
|
175
189
|
|
@@ -73,4 +73,44 @@ describe Bogus::MockingDSL do
|
|
73
73
|
baz.foo("bar").should == :return_value
|
74
74
|
end
|
75
75
|
end
|
76
|
+
|
77
|
+
describe "#fake" do
|
78
|
+
include Bogus::MockingDSL
|
79
|
+
|
80
|
+
it "creates objects that can be stubbed" do
|
81
|
+
greeter = fake
|
82
|
+
|
83
|
+
stub(greeter).greet("Jake") { "Hello Jake" }
|
84
|
+
|
85
|
+
greeter.greet("Jake").should == "Hello Jake"
|
86
|
+
end
|
87
|
+
|
88
|
+
it "creates objects that can be mocked" do
|
89
|
+
greeter = fake
|
90
|
+
|
91
|
+
mock(greeter).greet("Jake") { "Hello Jake" }
|
92
|
+
|
93
|
+
greeter.greet("Jake").should == "Hello Jake"
|
94
|
+
end
|
95
|
+
|
96
|
+
it "creates objects with some methods stubbed by default" do
|
97
|
+
greeter = fake(greet: "Hello Jake")
|
98
|
+
|
99
|
+
greeter.greet("Jake").should == "Hello Jake"
|
100
|
+
end
|
101
|
+
|
102
|
+
it "creates objects that can be spied upon" do
|
103
|
+
greeter = fake
|
104
|
+
|
105
|
+
greeter.greet("Jake")
|
106
|
+
|
107
|
+
greeter.should have_received.greet("Jake")
|
108
|
+
end
|
109
|
+
|
110
|
+
it "allows chaining interactions" do
|
111
|
+
greeter = fake(foo: "bar")
|
112
|
+
|
113
|
+
greeter.baz.foo.should == "bar"
|
114
|
+
end
|
115
|
+
end
|
76
116
|
end
|
@@ -67,5 +67,28 @@ describe Bogus::VerifiesStubDefinition do
|
|
67
67
|
it_disallows_argument_numbers :var_args, 0
|
68
68
|
end
|
69
69
|
end
|
70
|
+
|
71
|
+
class UsesMethodMissing
|
72
|
+
def respond_to?(method)
|
73
|
+
method == :foo
|
74
|
+
end
|
75
|
+
|
76
|
+
def method_missing(name, *args, &block)
|
77
|
+
return super unless name == :foo
|
78
|
+
:bar
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "with objects that use method missing" do
|
83
|
+
let(:object) { UsesMethodMissing.new }
|
84
|
+
|
85
|
+
it "allows stubbing methods that the object responds to" do
|
86
|
+
it_allows(:foo, [])
|
87
|
+
end
|
88
|
+
|
89
|
+
it "disallows stubbing methods that the object does not respond to" do
|
90
|
+
it_disallows(:bar, [], NameError)
|
91
|
+
end
|
92
|
+
end
|
70
93
|
end
|
71
94
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bogus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-11-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: dependor
|
@@ -198,12 +198,14 @@ files:
|
|
198
198
|
- .gitignore
|
199
199
|
- .pelusa.yml
|
200
200
|
- .travis.yml
|
201
|
+
- CHANGELOG.md
|
201
202
|
- Gemfile
|
202
203
|
- Gemfile.lock
|
203
204
|
- Guardfile
|
204
205
|
- README.md
|
205
206
|
- Rakefile
|
206
207
|
- bogus.gemspec
|
208
|
+
- features/anonymous_doubles.feature
|
207
209
|
- features/configuration_options.feature
|
208
210
|
- features/contract_tests_mocks.feature
|
209
211
|
- features/contract_tests_spies.feature
|
@@ -221,6 +223,7 @@ files:
|
|
221
223
|
- lib/bogus/contract_not_fulfilled.rb
|
222
224
|
- lib/bogus/converts_name_to_class.rb
|
223
225
|
- lib/bogus/copies_classes.rb
|
226
|
+
- lib/bogus/creates_anonymous_stubs.rb
|
224
227
|
- lib/bogus/creates_fakes.rb
|
225
228
|
- lib/bogus/double.rb
|
226
229
|
- lib/bogus/fake.rb
|
@@ -280,7 +283,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
280
283
|
version: '0'
|
281
284
|
segments:
|
282
285
|
- 0
|
283
|
-
hash: -
|
286
|
+
hash: -343777807
|
284
287
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
285
288
|
none: false
|
286
289
|
requirements:
|
@@ -289,7 +292,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
289
292
|
version: '0'
|
290
293
|
segments:
|
291
294
|
- 0
|
292
|
-
hash: -
|
295
|
+
hash: -343777807
|
293
296
|
requirements: []
|
294
297
|
rubyforge_project: bogus
|
295
298
|
rubygems_version: 1.8.24
|