bogus 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,5 +2,4 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.2
4
4
  - 1.9.3
5
- - rbx-19mode
6
5
  script: bundle exec rspec spec && bundle exec cucumber --tag ~@wip
@@ -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.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bogus (0.0.1)
4
+ bogus (0.0.2)
5
5
  dependor (>= 0.0.4)
6
6
  rr
7
7
 
@@ -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
+ """
@@ -5,9 +5,7 @@ Given /^a spec file named "([^"]*)" with:$/ do |file_name, string|
5
5
  steps %Q{
6
6
  Given a file named "#{file_name}" with:
7
7
  """ruby
8
- require 'bogus'
9
8
  require 'bogus/rspec'
10
- require 'rr'
11
9
 
12
10
  require_relative 'foo'
13
11
 
@@ -1,35 +1,13 @@
1
1
  require 'dependor'
2
2
 
3
- module Bogus
4
- autoload :AddsRecording, 'bogus/adds_recording'
5
- autoload :Configuration, 'bogus/configuration'
6
- autoload :ContractNotFulfilled, 'bogus/contract_not_fulfilled'
7
- autoload :ConvertsNameToClass, 'bogus/converts_name_to_class'
8
- autoload :CopiesClasses, 'bogus/copies_classes'
9
- autoload :CreatesFakes, 'bogus/creates_fakes'
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
@@ -25,16 +25,20 @@ module Bogus
25
25
  @injector = Bogus::Injector.new
26
26
  end
27
27
 
28
- def create_stub(object)
29
- inject.create_stub(object)
28
+ def create_stub(*args)
29
+ inject.create_stub(*args)
30
30
  end
31
31
 
32
- def create_mock(object)
33
- inject.create_mock(object)
32
+ def create_mock(*args)
33
+ inject.create_mock(*args)
34
34
  end
35
35
 
36
- def have_received(method = nil)
37
- inject.invocation_matcher(method)
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
@@ -1,3 +1,5 @@
1
+ require 'bogus'
2
+
1
3
  RSpec.configure do |config|
2
4
  config.extend Bogus::RSpecExtensions
3
5
  config.include Bogus::MockingDSL
@@ -16,16 +16,20 @@ module Bogus
16
16
  end
17
17
 
18
18
  module MockingDSL
19
- def stub(object)
20
- Bogus.create_stub(object)
19
+ def fake(*args)
20
+ Bogus.create_anonymous_stub(*args)
21
21
  end
22
22
 
23
- def have_received(method = nil)
24
- Bogus.have_received(method)
23
+ def stub(*args)
24
+ Bogus.create_stub(*args)
25
25
  end
26
26
 
27
- def mock(object)
28
- Bogus.create_mock(object)
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)
@@ -1,3 +1,3 @@
1
1
  module Bogus
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -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.1
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-07-30 00:00:00.000000000 Z
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: -1064750600305128815
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: -1064750600305128815
295
+ hash: -343777807
293
296
  requirements: []
294
297
  rubyforge_project: bogus
295
298
  rubygems_version: 1.8.24