fakes 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ blah.rb
2
+ *.gem
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/*
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.3@developwithpassion_fakes --create
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ guard 'rspec' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
data/README.md ADDED
@@ -0,0 +1,229 @@
1
+ #fakes
2
+
3
+ This is a really simple library to aid in AAA style testing. The primary driver for using this is to be able to make assertions on method calls to collaborators in actual assertions and not as part of setup. It is meant to be used to complement the current testing framework that you are using to aid in the creation of interaction based tests.
4
+
5
+ Here is a simple example
6
+
7
+ ```ruby
8
+ class SomeClass
9
+ def initialize(collaborator)
10
+ @collaborator = collaborator
11
+ end
12
+ def run()
13
+ @collaborator.send_message("Hi")
14
+ end
15
+ end
16
+
17
+ describe SomeClass do
18
+ context "when run" do
19
+ let(:collaborator){fake}
20
+ let(:sut){SomeClass.new(collaborator)}
21
+
22
+ before(:each) do
23
+ sut.run
24
+ end
25
+
26
+ it "should trigger its collaborator with the correct message" do
27
+ collaborator.received(:send_message).called_with("Hi").should_not be_nil
28
+ end
29
+ end
30
+ end
31
+ ```
32
+
33
+ ##Creating a new fake
34
+
35
+ To create a new fake, simply leverage the fake method that is mixed into the Kernel module.
36
+
37
+ ```ruby
38
+ require 'fakes'
39
+
40
+ item = fake
41
+ ```
42
+
43
+ ##Specifying the behaviour of a fake
44
+
45
+ When scaffolding fake return values, the library behaves almost identically to the way RSpec stubs work.
46
+
47
+ ###Setup a method to return a value for a particular set of arguments
48
+ ```ruby
49
+ collaborator = fake
50
+
51
+ collaborator.stub(:name_of_method).with(arg1,arg2,arg3).and_return(return_value)
52
+ ```
53
+
54
+ ###Setup a method to return a value regardless of the arguments it is called with
55
+ ```ruby
56
+ collaborator = fake
57
+
58
+ #long handed way
59
+ collaborator.stub(:name_of_method).ignore_arg.and_return(return_value)
60
+
61
+ #preferred way
62
+ collaborator.stub(:name_of_method).and_return(return_value)
63
+ ```
64
+
65
+ ###Setup different return values for different argument sets
66
+ ```ruby
67
+ collaborator = fake
68
+
69
+ #Setup a return value for 1
70
+ collaborator.stub(:method).with(1).and_return(first_return_value)
71
+
72
+ #Setup a return value for 2
73
+ collaborator.stub(:method).with(2).and_return(second_return_value)
74
+
75
+ #Setup a return value when called with everything else
76
+ #if you are going to use this, make sure it is used after
77
+ #setting up return values for specific arguments
78
+ collaborator.stub(:method).and_return(value_to_return_with_arguments_other_than_1_and_2)
79
+ ```
80
+
81
+ ##Verifying calls made to the fake
82
+
83
+
84
+ ###Verifying when a call was made
85
+
86
+ The primary purpose of the library is to help you in doing interaction style testing in a AAA style. Assume the following class is one you would like to test:
87
+
88
+ ```ruby
89
+ class ItemToTest
90
+ def initialize(collaborator)
91
+ @collaborator = collaborator
92
+ end
93
+
94
+ def run
95
+ @collaborator.send_message("Hello World")
96
+ end
97
+ end
98
+ ```
99
+
100
+ ItemToTest is supposed to leverage its collaborator and calls its send_message method with the argument "Hello World". To verify this using AAA style, interaction testing you can do the following (I am using rspec, but you can use this with any testing library you wish):
101
+
102
+ ```ruby
103
+ describe ItemToTest do
104
+ context "when run" do
105
+ let(:collaborator){fake}
106
+ let(:sut){ItemToTest.new(collaborator)}
107
+
108
+ #I typically use a before block to specifically trigger the method that I am testing, so it cleanly
109
+ #separates it from the assertions I will make later
110
+ before(:each) do
111
+ sut.run
112
+ end
113
+
114
+ it "should trigger its collaborator with the correct message" do
115
+ collaborator.received(:send_message).called_with("Hello World").should_not be_nil
116
+ end
117
+ end
118
+ end
119
+ ```
120
+ From the example above, you can see that we created the fake and did not need to scaffold it with any behaviour.
121
+
122
+ ```ruby
123
+ let(:collaborator){fake}
124
+ ```
125
+
126
+ You can also see that we are create our System Under Test (sut) and provide it the collaborator:
127
+
128
+ ```ruby
129
+ let(:sut){ItemToTest.new(collaborator)}
130
+ ```
131
+
132
+ We then proceed to invoke the method on the component we are testing
133
+
134
+ ```ruby
135
+ before(:each) do
136
+ sut.run
137
+ end
138
+ ```
139
+
140
+ Last but not least, we verify that our collaborator was invoked and with the right arguments:
141
+
142
+ ```ruby
143
+ it "should trigger its collaborator with the correct message" do
144
+ collaborator.received(:send_message).called_with("Hello World").should_not be_nil
145
+ end
146
+ ```
147
+
148
+ The nice thing is we can make the assertions after the fact, as opposed to needing to do them as part of setup, which I find is a much more natural way to read things, when you need to do this style of test. Notice that the called_with method return a method_invocation that will be nil if the call was not received. My recommendation would be to create a test utility method that allows you to leverage your testing frameworks assertion library to make the above assertion more terse. The
149
+ following rspec sample demonstrates:
150
+
151
+ ```ruby
152
+ module RSpec
153
+ Matchers.define :have_received do|symbol,*args|
154
+ match do|fake|
155
+ fake.received(symbol).called_with(*args) != nil
156
+ end
157
+ end
158
+ end
159
+ ```
160
+
161
+ Using the above utility method turns the previous assertion:
162
+
163
+ ```ruby
164
+ collaborator.received(:send_message).called_with("Hello World").should_not be_nil
165
+ ```
166
+
167
+ To this:
168
+
169
+ ```ruby
170
+ collaborator.should have_received(:send_message,"Hello World")
171
+ ```
172
+
173
+ ###Verifying that a call should not have been made
174
+
175
+ Currently verifying that a call was not made does not take the arguments into consideration. It just ensures that no calls to a particular named method were made. Here is an example:
176
+
177
+ ```ruby
178
+ class FirstCollaborator
179
+ def send_message(message)
180
+ end
181
+ end
182
+ class SecondCollaborator
183
+ def send_message(message)
184
+ end
185
+ end
186
+
187
+ class SomeItem
188
+ def initialize
189
+ @first = FirstCollaborator.new
190
+ @second = SecondCollaborator.new
191
+ end
192
+
193
+ def first_behaviour
194
+ @first.send_message("Hello")
195
+ end
196
+
197
+ def second_behaviour
198
+ @second.send_message("World")
199
+ end
200
+ end
201
+
202
+ describe SomeItem do
203
+ context "when run" do
204
+ let(:first){fake}
205
+ let(:second){fake}
206
+
207
+ before(:each) do
208
+ FirstCollaborator.stub(:new).and_return(first)
209
+ SecondCollaborator.stub(:new).and_return(second)
210
+ @sut = SomeItem.new
211
+ end
212
+
213
+ before(:each) do
214
+ @sut.first_behaviour
215
+ end
216
+
217
+ it "should trigger its collaborator with the correct message" do
218
+ first.should have_received(:send_message,"Hello")
219
+ end
220
+
221
+ it "should not trigger its second collaborator" do
222
+ #again, here would be another option to use a convienience test utility method
223
+ second.never_received?(:send_message).should be_true
224
+ end
225
+ end
226
+ end
227
+ ```
228
+
229
+ As you can see, in this test we want to verify that one collaborator was triggered and the other not.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/fakes.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib",__FILE__)
3
+ require "fakes/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "fakes"
7
+ s.version = Fakes::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Develop With Passion®"]
10
+ s.email = ["open_source@developwithpassion.com"]
11
+ s.homepage = "http://www.developwithpassion.com"
12
+ s.summary = %q{Simple faking library}
13
+ s.description = %q{Faking library that allows inspection of received calls after they have been made. Also supports tracking calls with multiple argument sets.}
14
+ s.rubyforge_project = "fakes"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency "rspec"
23
+ s.add_development_dependency "rake"
24
+ s.add_development_dependency "guard"
25
+ s.add_development_dependency "guard-rspec"
26
+ s.add_runtime_dependency "developwithpassion_arrays"
27
+ end
data/lib/fakes.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'developwithpassion_arrays'
2
+ require 'fakes/arg_behaviour'
3
+ require 'fakes/arg_set'
4
+ require 'fakes/fake'
5
+ require 'fakes/ignore_set'
6
+ require 'fakes/method_stub'
7
+
8
+ module Kernel
9
+ def fake
10
+ return Fakes::Fake.new
11
+ end
12
+ end
@@ -0,0 +1,22 @@
1
+ module Fakes
2
+ module ArgBehaviour
3
+ attr_accessor :return_value,:times_called
4
+
5
+ def and_return(item)
6
+ @return_value = item
7
+ end
8
+
9
+ def capture_args(args)
10
+ @times_called += 1
11
+ @called_args = args
12
+ end
13
+
14
+ def matches?(args)
15
+ return @args == args
16
+ end
17
+
18
+ def was_called_with?(args)
19
+ return @called_args == args
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,10 @@
1
+ module Fakes
2
+ class ArgSet
3
+ include ArgBehaviour
4
+
5
+ def initialize(args)
6
+ @args = args
7
+ @times_called = 0
8
+ end
9
+ end
10
+ end
data/lib/fakes/fake.rb ADDED
@@ -0,0 +1,29 @@
1
+ module Fakes
2
+ class Fake
3
+ def initialize(invocation_set = {})
4
+ @method_invocations = invocation_set
5
+ end
6
+
7
+ def method_missing(name,*args,&block)
8
+ return @method_invocations.has_key?(name.to_sym) ? @method_invocations[name.to_sym].invoke(args) : handle_unexpected_method_invocation(name,args,block)
9
+ end
10
+
11
+ def handle_unexpected_method_invocation(name,args,block)
12
+ method = stub(name.to_sym)
13
+ method.ignore_arg
14
+ return method.invoke(args)
15
+ end
16
+
17
+ def stub(symbol)
18
+ return @method_invocations[symbol] || @method_invocations[symbol] = MethodStub.new
19
+ end
20
+
21
+ def received(symbol)
22
+ return @method_invocations[symbol]
23
+ end
24
+
25
+ def never_received?(symbol)
26
+ return !@method_invocations.has_key?(symbol)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,24 @@
1
+ module Fakes
2
+ class IgnoreSet
3
+ include ArgBehaviour
4
+
5
+ def initialize
6
+ array :arg_sets do|a|
7
+ a.mutator :capture_args do|args|
8
+ @times_called += 1
9
+ @arg_sets << args
10
+ end
11
+ end
12
+ @times_called = 0
13
+ end
14
+
15
+ def matches?(args)
16
+ return true
17
+ end
18
+
19
+
20
+ def was_called_with?(args)
21
+ return @arg_sets.select{|set| set == args}.count > 0
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,45 @@
1
+ module Fakes
2
+ class MethodStub
3
+ def initialize(arg_sets = [])
4
+ array :arg_sets do|a|
5
+ a.mutator :add_new_set do|set|
6
+ @arg_sets << set
7
+ set
8
+ end
9
+ end
10
+ @arg_sets = arg_sets
11
+ end
12
+
13
+ def with(*args)
14
+ return add_new_set(ArgSet.new(args))
15
+ end
16
+
17
+
18
+ def ignore_arg
19
+ return add_new_set(IgnoreSet.new)
20
+ end
21
+
22
+ def and_return(item)
23
+ ignore_arg.and_return(item)
24
+ end
25
+
26
+
27
+ def invoke(args)
28
+ set = @arg_sets.find{|item| item.matches?(args)} || ignore_arg
29
+ set.capture_args(args)
30
+ return set.return_value
31
+ end
32
+
33
+ def called_with(*args)
34
+ return @arg_sets.find{|item| item.was_called_with?(args)}
35
+ end
36
+
37
+ def total_times_called
38
+ return @arg_sets.inject(0){|sum,item|sum += item.times_called}
39
+ end
40
+
41
+ def times?(value)
42
+ return total_times_called == value
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,3 @@
1
+ module Fakes
2
+ VERSION = "0.1.2"
3
+ end
@@ -0,0 +1,3 @@
1
+ Dir.chdir(File.join(File.dirname(__FILE__),"..,lib".split(','))) do
2
+ require 'fakes.rb'
3
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ module Fakes
4
+ describe ArgBehaviour do
5
+ class AnArg
6
+ attr_accessor :called_args,:args
7
+ def initialize
8
+ @times_called = 0
9
+ end
10
+ end
11
+
12
+ let(:sut){AnArg.new}
13
+ before (:each) do
14
+ sut.send(:extend,ArgBehaviour)
15
+ end
16
+ context "when a return value is specified" do
17
+ before (:each) do
18
+ sut.and_return(2)
19
+ end
20
+ it "should store the return value to be returned during invocation" do
21
+ sut.return_value.should == 2
22
+ end
23
+ end
24
+
25
+ context "when handling an invocation" do
26
+ before (:each) do
27
+ sut.capture_args(2)
28
+ end
29
+ it "should increment the number of times it was called" do
30
+ sut.times_called.should == 1
31
+ end
32
+ it "should store the arguments it was called with" do
33
+ sut.called_args.should == 2
34
+ end
35
+ end
36
+
37
+ context "when matching a set of arguments" do
38
+ before (:each) do
39
+ sut.args = 2
40
+ end
41
+ it "should match if its own set of arguments are the same" do
42
+ sut.matches?(2).should be_true
43
+ sut.matches?(3).should be_false
44
+ end
45
+ end
46
+
47
+ context "when matching a set of arguments that is passed in as a dictionary" do
48
+ before (:each) do
49
+ sut.args = {:id => 0,:name => "JP"}
50
+ end
51
+ it "should match if its hash is the same" do
52
+ sut.matches?(:id => 0,:name => "JP").should be_true
53
+ end
54
+ end
55
+
56
+ context "when determining whether it was called with a set of arguments" do
57
+ before (:each) do
58
+ sut.called_args = 2
59
+ end
60
+
61
+ it "should match if the arguments are the same as the arguments it was invoked with" do
62
+ sut.was_called_with?(2).should be_true
63
+ sut.was_called_with?(3).should be_false
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ module Fakes
4
+ describe ArgSet do
5
+ context "when created" do
6
+ let(:sut){ArgSet.new(1)}
7
+
8
+ it "should initialize required members" do
9
+ sut.times_called.should == 0
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,220 @@
1
+ require 'spec_helper'
2
+
3
+ module Fakes
4
+ describe Fake do
5
+ context "when stubbing a method" do
6
+ let(:invocations){Hash.new}
7
+ let(:sut){Fake.new(invocations)}
8
+ let(:symbol){:hello}
9
+ let(:new_method){Object.new}
10
+
11
+ context "and the method is not currently setup to be called" do
12
+ before (:each) do
13
+ MethodStub.stub(:new).and_return(new_method)
14
+ end
15
+ before (:each) do
16
+ @result = sut.stub(symbol)
17
+ end
18
+ it "should add a new method stub to the list of all invocations" do
19
+ invocations[symbol].should == new_method
20
+ end
21
+ it "should return the method invocation to continue specifying call behaviour" do
22
+ @result.should == new_method
23
+ end
24
+ end
25
+
26
+ context "and the method is already in the list of invocations" do
27
+ before (:each) do
28
+ invocations[symbol] = new_method
29
+ end
30
+ before (:each) do
31
+ @result = sut.stub(symbol)
32
+ end
33
+
34
+ it "should not readd the method to the list of invocations" do
35
+ invocations.count.should == 1
36
+ end
37
+
38
+ it "should return the method invocation to continue specifying call behaviour" do
39
+ @result.should == new_method
40
+ end
41
+ end
42
+ end
43
+ context "when accessing the behaviour for a received call" do
44
+ let(:invocations){Hash.new}
45
+ let(:sut){Fake.new(invocations)}
46
+ let(:symbol){:hello}
47
+ let(:method_invocation){Object.new}
48
+
49
+ before (:each) do
50
+ invocations[symbol] = method_invocation
51
+ end
52
+ before (:each) do
53
+ @result = sut.received(symbol)
54
+ end
55
+ it "should return the method invocation for the called method" do
56
+ @result.should == method_invocation
57
+ end
58
+ end
59
+ context "when verifying whether a call was never received" do
60
+ let(:invocations){Hash.new}
61
+ let(:sut){Fake.new(invocations)}
62
+ let(:existing){:hello}
63
+ let(:method_invocation){Object.new}
64
+
65
+ before (:each) do
66
+ invocations[existing] = method_invocation
67
+ end
68
+
69
+
70
+ it "should base its decision on the list of received invocations" do
71
+ [:other,existing].each do|item|
72
+ sut.never_received?(item).should_not be_equal(invocations.has_key?(item))
73
+ end
74
+ end
75
+ end
76
+ context "when method missing is triggered" do
77
+ class FakeInvocation
78
+ attr_accessor :invoke_was_called,:args,:return_value,:ignores_args
79
+
80
+ def initialize(return_value)
81
+ @return_value = return_value
82
+ end
83
+
84
+ def invoke(args)
85
+ @args = args
86
+ return @return_value
87
+ end
88
+
89
+ def ignore_arg
90
+ @ignores_args = true
91
+ end
92
+ end
93
+ let(:invocations){Hash.new}
94
+ let(:sut){Fake.new(invocations)}
95
+ let(:symbol){:hello}
96
+ let(:invocation){FakeInvocation.new(Object.new)}
97
+ let(:args){"world"}
98
+ context "and the method is for an invocation that was prepared" do
99
+ before (:each) do
100
+ invocations[symbol] = invocation
101
+ end
102
+ before (:each) do
103
+ @result = sut.hello(args)
104
+ end
105
+ it "should trigger the invocation with the arguments" do
106
+ invocation.args.should == [args]
107
+ end
108
+ it "should return the result of triggering the invocation" do
109
+ @result.should == invocation.return_value
110
+ end
111
+ end
112
+ context "and the method is for an invocation that was not prepared" do
113
+ before (:each) do
114
+ MethodStub.stub(:new).and_return(invocation)
115
+ end
116
+ before (:each) do
117
+ @result = sut.hello(args)
118
+ end
119
+ it "should add a new invocation which ignores arguments to the list of all invocations" do
120
+ invocations.has_key?(:hello).should be_true
121
+ end
122
+
123
+ it "should configure the new invocation to ignore all arguments" do
124
+ invocation.ignores_args.should be_true
125
+ end
126
+
127
+ it "should invoke the invocation with the arguments" do
128
+ invocation.args.should == [args]
129
+ end
130
+
131
+ it "should return the result of triggering the new invocation" do
132
+ @result.should == invocation.return_value
133
+ end
134
+ end
135
+ end
136
+
137
+ context "scenarios" do
138
+ context "setting up return values" do
139
+ it "should be able to intercept on methods that take a singular value" do
140
+ fake = Fake.new
141
+ fake.stub(:hello).with("World").and_return("Hello World")
142
+ fake.hello("World").should == "Hello World"
143
+ end
144
+
145
+ it "should be able to intercept on methods that take a hash" do
146
+ fake = Fake.new
147
+ fake.stub(:hello).with(:id => "JP",:age => 33).and_return("Hello World")
148
+ fake.hello(:id => "JP",:age => 33).should == "Hello World"
149
+ end
150
+
151
+ it "should be able to intercept on methods that take a value and a hash" do
152
+ fake = Fake.new
153
+ fake.stub(:hello).with(1,:id => "JP",:age => 33).and_return("Hello World")
154
+
155
+ fake.hello(1,:id => "JP",:age => 33).should == "Hello World"
156
+ fake.hello(2,:id => "JP",:age => 33).should be_nil
157
+ end
158
+
159
+ it "should be able to intercept on methods that take an array" do
160
+ fake = Fake.new
161
+ fake.stub(:hello).with([1,2,3,4]).and_return("Hello World")
162
+
163
+ fake.hello([1,2,3,4]).should == "Hello World"
164
+ end
165
+
166
+ it "should be able to intercept on methods that take an value, and an array" do
167
+ fake = Fake.new
168
+ fake.stub(:hello).with(1,[1,2,3,4]).and_return("Hello World")
169
+
170
+ fake.hello(1,[1,2,3,4]).should == "Hello World"
171
+ end
172
+ end
173
+ context "verifying calls were made" do
174
+ it "should be able to intercept on methods that take a singular value" do
175
+ fake = Fake.new
176
+ fake.hello("World")
177
+ fake.received(:hello).called_with("World").should be_true
178
+ end
179
+
180
+ it "should be able to intercept on methods that have no arguments" do
181
+ fake = Fake.new
182
+ fake.hello
183
+ fake.received(:hello).should_not be_nil
184
+ end
185
+
186
+
187
+ it "should be able to intercept on methods that take a hash" do
188
+ fake = Fake.new
189
+ fake.hello(:id => "JP",:age => 33)
190
+ fake.received(:hello).called_with(:id => "JP",:age => 33).should_not be_nil
191
+ fake.received(:hello).called_with(:id => "JS",:age => 33).should be_nil
192
+ end
193
+
194
+ it "should be able to intercept on methods that take a value and a hash" do
195
+ fake = Fake.new
196
+
197
+ fake.hello(1,:id => "JP",:age => 33)
198
+ fake.received(:hello).called_with(1,:id => "JP",:age => 33).should_not be_nil
199
+ fake.received(:hello).called_with(1,:id => "JS",:age => 33).should be_nil
200
+ end
201
+
202
+ it "should be able to intercept on methods that take an array" do
203
+ fake = Fake.new
204
+
205
+ fake.hello([1,2,3,4])
206
+ fake.received(:hello).called_with([1,2,3,4]).should_not be_nil
207
+ fake.received(:hello).called_with([1,2,3,5]).should be_nil
208
+ end
209
+
210
+ it "should be able to intercept on methods that take an value, and an array" do
211
+ fake = Fake.new
212
+ fake.hello(1,[1,2,3,4])
213
+
214
+ fake.received(:hello).called_with(1,[1,2,3,4]).should_not be_nil
215
+ fake.received(:hello).called_with(1,[1,2,3,5]).should be_nil
216
+ end
217
+ end
218
+ end
219
+ end
220
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ module Fakes
4
+ describe IgnoreSet do
5
+ let(:sut){IgnoreSet.new}
6
+
7
+ context "when created" do
8
+ it "should initialize required members" do
9
+ sut.times_called.should == 0
10
+ end
11
+ end
12
+
13
+ context "when matching an argument set" do
14
+ it "should match any argument set" do
15
+ sut.matches?([1,2,3,4]).should be_true
16
+ sut.matches?([3,"hello",4,5]).should be_true
17
+ end
18
+ end
19
+
20
+ context "when capturing a set of arguments" do
21
+ before (:each) do
22
+ sut.capture_args(1)
23
+ sut.capture_args(2)
24
+ end
25
+ it "should store a list for each set of arguments" do
26
+ sut.arg_sets.count.should == 2
27
+ end
28
+ end
29
+
30
+ context "when determining if it was called with a set of arguments" do
31
+ before (:each) do
32
+ sut.capture_args(1)
33
+ sut.capture_args(2)
34
+ end
35
+ it "should match if any of its argument sets match" do
36
+ sut.was_called_with?(2).should be_true
37
+ end
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,6 @@
1
+ describe Kernel do
2
+ it "should be able to create a new fake using the kernel exposed method" do
3
+ fake.class.should == Fakes::Fake
4
+ end
5
+ end
6
+
@@ -0,0 +1,167 @@
1
+ require 'spec_helper'
2
+
3
+ module Fakes
4
+ describe MethodStub do
5
+ let(:args){[1,2,3]}
6
+ let(:argument_set){Object.new}
7
+
8
+ context "when specifying a set of arguments it should be called with" do
9
+ let(:arg_sets){[]}
10
+ let(:sut){MethodStub.new(arg_sets)}
11
+
12
+ before (:each) do
13
+ ArgSet.stub(:new).with([args]).and_return(argument_set)
14
+ end
15
+ before (:each) do
16
+ @result = sut.with(args)
17
+ end
18
+ it "should add a new argument set to its list of arguments" do
19
+ arg_sets[0].should == argument_set
20
+ end
21
+ it "should return the argument set to continue specifying behaviour" do
22
+ @result.should == argument_set
23
+ end
24
+ end
25
+
26
+ context "when ignoring arguments" do
27
+ let(:ignored_set){Object.new}
28
+ let(:arg_sets){[]}
29
+ let(:sut){MethodStub.new(arg_sets)}
30
+
31
+ before (:each) do
32
+ IgnoreSet.stub(:new).and_return(ignored_set)
33
+ end
34
+ before (:each) do
35
+ @result = sut.ignore_arg
36
+ end
37
+ it "should add the ignored set to the list of argument sets" do
38
+ arg_sets[0].should == ignored_set
39
+ end
40
+ it "should return the ignored set to specify other behaviour" do
41
+ @result.should == ignored_set
42
+ end
43
+ end
44
+
45
+ context "when invoked with a set of arguments" do
46
+ let(:arg_sets){[]}
47
+ let(:sut){MethodStub.new(arg_sets)}
48
+ class DummyArgSet
49
+ attr_accessor :args
50
+
51
+ def capture_args(*args)
52
+ @args = *args
53
+ end
54
+ end
55
+ context "and it has the specified argument set" do
56
+ let(:arguments){[1]}
57
+ let(:arg_set){DummyArgSet.new}
58
+ before (:each) do
59
+ arg_sets.push(arg_set)
60
+ arg_set.stub(:matches?).and_return(true)
61
+ arg_set.stub(:return_value).and_return(2)
62
+ end
63
+ before (:each) do
64
+ @result = sut.invoke(arguments)
65
+ end
66
+ it "should tell the argument set to capture the arguments it was called with" do
67
+ arg_set.args.should == [arguments]
68
+ end
69
+ it "should return using from the arg set" do
70
+ @result.should == 2
71
+ end
72
+
73
+ end
74
+ context "and it does not have the specified argument set" do
75
+ let(:arguments){[1]}
76
+ let(:arg_set){DummyArgSet.new}
77
+ before (:each) do
78
+ sut.stub(:ignore_arg).and_return(arg_set)
79
+ arg_set.stub(:return_value).and_return(2)
80
+ end
81
+ before (:each) do
82
+ @result = sut.invoke(arguments)
83
+ end
84
+ it "should tell the argument set to capture the arguments it was called with" do
85
+ arg_set.args.should == [arguments]
86
+ end
87
+ it "should return using from the missing arg set" do
88
+ @result.should == 2
89
+ end
90
+ end
91
+
92
+ end
93
+
94
+ context "when determining whether it was called with a set of arguments" do
95
+ let(:arg_sets){[]}
96
+ let(:sut){MethodStub.new(arg_sets)}
97
+ class DummyArgSet
98
+ attr_accessor :args
99
+
100
+ def capture_args(*args)
101
+ @args = *args
102
+ end
103
+ end
104
+ let(:arguments){1}
105
+
106
+ context "and one of its argument sets was called with the set of arguments" do
107
+ let(:arg_set){DummyArgSet.new}
108
+ before (:each) do
109
+ arg_sets.push(arg_set)
110
+ arg_set.stub(:was_called_with?).with([arguments]).and_return(true)
111
+ end
112
+ before (:each) do
113
+ @result = sut.called_with(arguments)
114
+ end
115
+
116
+ it "should return the argument set that was called with the arguments" do
117
+ @result.should == arg_set
118
+ end
119
+ end
120
+ context "and none of its argument sets were called with the arguments" do
121
+ before (:each) do
122
+ @result = sut.called_with(arguments)
123
+ end
124
+ it "should return nil" do
125
+ @result.should be_nil
126
+ end
127
+ end
128
+
129
+ end
130
+
131
+ context "when retrieving the total number of times called" do
132
+ let(:arg_sets){[]}
133
+ let(:sut){MethodStub.new(arg_sets)}
134
+ let(:arg_set){DummyArgSet.new}
135
+ let(:arg_set_2){DummyArgSet.new}
136
+
137
+ before (:each) do
138
+ arg_sets.push(arg_set)
139
+ arg_sets.push(arg_set_2)
140
+ arg_set.stub(:times_called).and_return(2)
141
+ arg_set_2.stub(:times_called).and_return(3)
142
+ end
143
+
144
+ it "it should return the sum of the invocations of its argument sets" do
145
+ sut.total_times_called.should == 5
146
+ end
147
+ end
148
+ context "when verifying whether it was called a certain number of times" do
149
+ let(:arg_sets){[]}
150
+ let(:sut){MethodStub.new(arg_sets)}
151
+ let(:arg_set){DummyArgSet.new}
152
+ let(:arg_set_2){DummyArgSet.new}
153
+
154
+ before (:each) do
155
+ arg_sets.push(arg_set)
156
+ arg_sets.push(arg_set_2)
157
+ arg_set.stub(:times_called).and_return(2)
158
+ arg_set_2.stub(:times_called).and_return(3)
159
+ end
160
+
161
+ it "it should return whether the sum of its argset invocations is the same as the number of request made" do
162
+ sut.times?(5).should be_true
163
+ sut.times?(3).should be_false
164
+ end
165
+ end
166
+ end
167
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fakes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Develop With Passion®
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: guard
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: guard-rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: developwithpassion_arrays
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: Faking library that allows inspection of received calls after they have
95
+ been made. Also supports tracking calls with multiple argument sets.
96
+ email:
97
+ - open_source@developwithpassion.com
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - .gitignore
103
+ - .rvmrc
104
+ - Gemfile
105
+ - Guardfile
106
+ - README.md
107
+ - Rakefile
108
+ - fakes.gemspec
109
+ - lib/fakes.rb
110
+ - lib/fakes/arg_behaviour.rb
111
+ - lib/fakes/arg_set.rb
112
+ - lib/fakes/fake.rb
113
+ - lib/fakes/ignore_set.rb
114
+ - lib/fakes/method_stub.rb
115
+ - lib/fakes/version.rb
116
+ - spec/spec_helper.rb
117
+ - spec/specs/arg_behaviour_spec.rb
118
+ - spec/specs/arg_set_spec.rb
119
+ - spec/specs/fake_spec.rb
120
+ - spec/specs/ignore_set_spec.rb
121
+ - spec/specs/kernel_spec.rb
122
+ - spec/specs/method_stub_spec.rb
123
+ homepage: http://www.developwithpassion.com
124
+ licenses: []
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ! '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubyforge_project: fakes
143
+ rubygems_version: 1.8.21
144
+ signing_key:
145
+ specification_version: 3
146
+ summary: Simple faking library
147
+ test_files:
148
+ - spec/spec_helper.rb
149
+ - spec/specs/arg_behaviour_spec.rb
150
+ - spec/specs/arg_set_spec.rb
151
+ - spec/specs/fake_spec.rb
152
+ - spec/specs/ignore_set_spec.rb
153
+ - spec/specs/kernel_spec.rb
154
+ - spec/specs/method_stub_spec.rb