rr 0.4.10 → 0.6.0
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/CHANGES +14 -0
- data/README.rdoc +67 -13
- data/Rakefile +1 -1
- data/lib/rr.rb +29 -9
- data/lib/rr/adapters/rr_methods.rb +38 -158
- data/lib/rr/double.rb +46 -41
- data/lib/rr/double_definitions/child_double_definition_creator.rb +23 -0
- data/lib/rr/double_definitions/double_definition.rb +212 -0
- data/lib/rr/double_definitions/double_definition_creator.rb +153 -0
- data/lib/rr/double_definitions/double_definition_creator_proxy.rb +25 -0
- data/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb +15 -0
- data/lib/rr/double_definitions/strategies/implementation/proxy.rb +62 -0
- data/lib/rr/double_definitions/strategies/implementation/reimplementation.rb +14 -0
- data/lib/rr/double_definitions/strategies/scope/instance.rb +15 -0
- data/lib/rr/double_definitions/strategies/scope/instance_of_class.rb +43 -0
- data/lib/rr/double_definitions/strategies/scope/scope_strategy.rb +15 -0
- data/lib/rr/double_definitions/strategies/strategy.rb +70 -0
- data/lib/rr/double_definitions/strategies/verification/dont_allow.rb +34 -0
- data/lib/rr/double_definitions/strategies/verification/mock.rb +44 -0
- data/lib/rr/double_definitions/strategies/verification/stub.rb +45 -0
- data/lib/rr/double_definitions/strategies/verification/verification_strategy.rb +15 -0
- data/lib/rr/double_injection.rb +21 -15
- data/lib/rr/expectations/argument_equality_expectation.rb +2 -1
- data/lib/rr/space.rb +23 -22
- data/lib/rr/wildcard_matchers/hash_including.rb +29 -0
- data/lib/rr/wildcard_matchers/satisfy.rb +26 -0
- data/spec/high_level_spec.rb +111 -64
- data/spec/rr/adapters/rr_methods_argument_matcher_spec.rb +1 -1
- data/spec/rr/adapters/rr_methods_creator_spec.rb +99 -315
- data/spec/rr/adapters/rr_methods_space_spec.rb +90 -109
- data/spec/rr/adapters/rr_methods_spec_helper.rb +1 -1
- data/spec/rr/adapters/rr_methods_times_matcher_spec.rb +1 -1
- data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +103 -0
- data/spec/rr/double_definitions/double_definition_creator_proxy_spec.rb +83 -0
- data/spec/rr/double_definitions/double_definition_creator_spec.rb +495 -0
- data/spec/rr/double_definitions/double_definition_spec.rb +1116 -0
- data/spec/rr/double_injection/double_injection_bind_spec.rb +111 -0
- data/spec/rr/double_injection/double_injection_dispatching_spec.rb +245 -0
- data/spec/rr/{double → double_injection}/double_injection_has_original_method_spec.rb +9 -9
- data/spec/rr/double_injection/double_injection_reset_spec.rb +90 -0
- data/spec/rr/double_injection/double_injection_spec.rb +77 -0
- data/spec/rr/double_injection/double_injection_verify_spec.rb +29 -0
- data/spec/rr/double_spec.rb +156 -136
- data/spec/rr/errors/rr_error_spec.rb +1 -1
- data/spec/rr/expectations/any_argument_expectation_spec.rb +1 -1
- data/spec/rr/expectations/anything_argument_equality_expectation_spec.rb +6 -30
- data/spec/rr/expectations/argument_equality_expectation_spec.rb +35 -18
- data/spec/rr/expectations/boolean_argument_equality_expectation_spec.rb +22 -41
- data/spec/rr/expectations/hash_including_argument_equality_expectation_spec.rb +82 -0
- data/spec/rr/expectations/hash_including_spec.rb +17 -0
- data/spec/rr/expectations/satisfy_argument_equality_expectation_spec.rb +59 -0
- data/spec/rr/expectations/satisfy_spec.rb +14 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +30 -28
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +55 -54
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +49 -48
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +9 -7
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +77 -76
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +58 -57
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +59 -58
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_spec.rb +25 -24
- data/spec/rr/rspec/rspec_adapter_spec.rb +12 -11
- data/spec/rr/rspec/rspec_backtrace_tweaking_spec.rb +10 -8
- data/spec/rr/rspec/rspec_usage_spec.rb +1 -1
- data/spec/rr/space/hash_with_object_id_key_spec.rb +1 -1
- data/spec/rr/space/space_spec.rb +330 -192
- data/spec/rr/test_unit/test_helper.rb +1 -2
- data/spec/rr/test_unit/test_unit_backtrace_test.rb +1 -2
- data/spec/rr/test_unit/test_unit_integration_test.rb +1 -2
- data/spec/rr/times_called_matchers/any_times_matcher_spec.rb +1 -1
- data/spec/rr/times_called_matchers/at_least_matcher_spec.rb +1 -1
- data/spec/rr/times_called_matchers/at_most_matcher_spec.rb +1 -1
- data/spec/rr/times_called_matchers/integer_matcher_spec.rb +1 -1
- data/spec/rr/times_called_matchers/proc_matcher_spec.rb +1 -1
- data/spec/rr/times_called_matchers/range_matcher_spec.rb +1 -1
- data/spec/rr/times_called_matchers/times_called_matcher_spec.rb +1 -1
- data/spec/rr/wildcard_matchers/anything_spec.rb +24 -0
- data/spec/rr/wildcard_matchers/boolean_spec.rb +36 -0
- data/spec/rr/wildcard_matchers/duck_type_spec.rb +52 -0
- data/spec/rr/wildcard_matchers/is_a_spec.rb +32 -0
- data/spec/rr/wildcard_matchers/numeric_spec.rb +32 -0
- data/spec/rr/wildcard_matchers/range_spec.rb +35 -0
- data/spec/rr/wildcard_matchers/regexp_spec.rb +43 -0
- data/spec/rr_spec.rb +28 -0
- data/spec/spec_helper.rb +84 -0
- metadata +43 -29
- data/lib/rr/double_creator.rb +0 -271
- data/lib/rr/double_definition.rb +0 -179
- data/lib/rr/double_definition_builder.rb +0 -44
- data/lib/rr/double_definition_creator.rb +0 -156
- data/lib/rr/double_definition_creator_proxy.rb +0 -20
- data/spec/rr/double/double_injection_bind_spec.rb +0 -105
- data/spec/rr/double/double_injection_dispatching_spec.rb +0 -228
- data/spec/rr/double/double_injection_reset_spec.rb +0 -86
- data/spec/rr/double/double_injection_spec.rb +0 -72
- data/spec/rr/double/double_injection_verify_spec.rb +0 -24
- data/spec/rr/double_definition_creator_proxy_spec.rb +0 -85
- data/spec/rr/double_definition_creator_spec.rb +0 -496
- data/spec/rr/double_definition_spec.rb +0 -815
- data/spec/rr/expectations/anything_spec.rb +0 -14
- data/spec/rr/expectations/boolean_spec.rb +0 -14
- data/spec/rr/expectations/duck_type_argument_equality_expectation_spec.rb +0 -71
- data/spec/rr/expectations/duck_type_spec.rb +0 -14
- data/spec/rr/expectations/is_a_argument_equality_expectation_spec.rb +0 -51
- data/spec/rr/expectations/is_a_spec.rb +0 -14
- data/spec/rr/expectations/numeric_argument_equality_expectation_spec.rb +0 -47
- data/spec/rr/expectations/numeric_spec.rb +0 -14
- data/spec/rr/expectations/range_argument_equality_expectation_spec.rb +0 -59
- data/spec/rr/expectations/range_spec.rb +0 -10
- data/spec/rr/expectations/regexp_argument_equality_expectation_spec.rb +0 -72
- data/spec/rr/expectations/regexp_spec.rb +0 -10
@@ -1,134 +1,115 @@
|
|
1
|
-
require "
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
|
2
2
|
|
3
3
|
module RR
|
4
4
|
module Adapters
|
5
|
-
describe RRMethods
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
@object2 = Object.new
|
15
|
-
@method_name = :foobar
|
16
|
-
end
|
5
|
+
describe RRMethods do
|
6
|
+
attr_reader :space, :subject_1, :subject_2, :method_name
|
7
|
+
it_should_behave_like "Swapped Space"
|
8
|
+
it_should_behave_like "RR::Adapters::RRMethods"
|
9
|
+
before do
|
10
|
+
@subject_1 = Object.new
|
11
|
+
@subject_2 = Object.new
|
12
|
+
@method_name = :foobar
|
13
|
+
end
|
17
14
|
|
18
|
-
|
19
|
-
|
15
|
+
describe "#verify" do
|
16
|
+
it "aliases #rr_verify" do
|
17
|
+
RRMethods.instance_method("verify").should == RRMethods.instance_method("rr_verify")
|
20
18
|
end
|
21
|
-
|
22
|
-
describe RRMethods, "#verify" do
|
23
|
-
it "#verify verifies and deletes the double_injections" do
|
24
|
-
verifies_all_double_injections {verify}
|
25
|
-
end
|
26
|
-
|
27
|
-
it "#rr_verify verifies and deletes the double_injections" do
|
28
|
-
verifies_all_double_injections {rr_verify}
|
29
|
-
end
|
19
|
+
end
|
30
20
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
define_method(:reset) do ||
|
43
|
-
double1_reset_calls += 1
|
44
|
-
end
|
21
|
+
describe "#rr_verify" do
|
22
|
+
it "verifies and deletes the double_injections" do
|
23
|
+
double_1 = space.double_injection(subject_1, method_name)
|
24
|
+
double_1_verify_calls = 0
|
25
|
+
double_1_reset_calls = 0
|
26
|
+
(
|
27
|
+
class << double_1;
|
28
|
+
self;
|
29
|
+
end).class_eval do
|
30
|
+
define_method(:verify) do ||
|
31
|
+
double_1_verify_calls += 1
|
45
32
|
end
|
46
|
-
|
47
|
-
|
48
|
-
double2_reset_calls = 0
|
49
|
-
(
|
50
|
-
class << double2;
|
51
|
-
self;
|
52
|
-
end).class_eval do
|
53
|
-
define_method(:verify) do ||
|
54
|
-
double2_verify_calls += 1
|
55
|
-
end
|
56
|
-
define_method(:reset) do ||
|
57
|
-
double2_reset_calls += 1
|
58
|
-
end
|
33
|
+
define_method(:reset) do ||
|
34
|
+
double_1_reset_calls += 1
|
59
35
|
end
|
60
|
-
|
61
|
-
yield
|
62
|
-
double1_verify_calls.should == 1
|
63
|
-
double2_verify_calls.should == 1
|
64
|
-
double1_reset_calls.should == 1
|
65
|
-
double1_reset_calls.should == 1
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
describe RRMethods, "#reset" do
|
70
|
-
it "#reset removes the ordered doubles" do
|
71
|
-
removes_ordered_doubles {reset}
|
72
36
|
end
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
37
|
+
double_2 = space.double_injection(subject_2, method_name)
|
38
|
+
double_2_verify_calls = 0
|
39
|
+
double_2_reset_calls = 0
|
40
|
+
(
|
41
|
+
class << double_2;
|
42
|
+
self;
|
43
|
+
end).class_eval do
|
44
|
+
define_method(:verify) do ||
|
45
|
+
double_2_verify_calls += 1
|
46
|
+
end
|
47
|
+
define_method(:reset) do ||
|
48
|
+
double_2_reset_calls += 1
|
49
|
+
end
|
80
50
|
end
|
81
51
|
|
82
|
-
|
83
|
-
|
84
|
-
|
52
|
+
rr_verify
|
53
|
+
double_1_verify_calls.should == 1
|
54
|
+
double_2_verify_calls.should == 1
|
55
|
+
double_1_reset_calls.should == 1
|
56
|
+
double_1_reset_calls.should == 1
|
57
|
+
end
|
58
|
+
end
|
85
59
|
|
86
|
-
|
87
|
-
|
88
|
-
|
60
|
+
describe "#reset" do
|
61
|
+
it "aliases #rr_reset" do
|
62
|
+
RRMethods.instance_method("reset").should == RRMethods.instance_method("rr_reset")
|
63
|
+
end
|
64
|
+
end
|
89
65
|
|
90
|
-
|
91
|
-
|
66
|
+
describe "#rr_reset" do
|
67
|
+
it "removes the ordered doubles" do
|
68
|
+
double_1 = new_double(
|
69
|
+
space.double_injection(subject_1, :foobar1),
|
70
|
+
RR::DoubleDefinitions::DoubleDefinition.new(creator = RR::DoubleDefinitions::DoubleDefinitionCreator.new, subject_1)
|
71
|
+
)
|
72
|
+
double_2 = new_double(
|
73
|
+
space.double_injection(subject_2, :foobar2),
|
74
|
+
RR::DoubleDefinitions::DoubleDefinition.new(creator = RR::DoubleDefinitions::DoubleDefinitionCreator.new, subject_2)
|
75
|
+
)
|
92
76
|
|
93
|
-
|
94
|
-
|
77
|
+
double_1.ordered
|
78
|
+
double_2.ordered
|
95
79
|
|
96
|
-
|
80
|
+
space.ordered_doubles.should_not be_empty
|
97
81
|
|
98
|
-
|
99
|
-
|
100
|
-
|
82
|
+
rr_reset
|
83
|
+
space.ordered_doubles.should be_empty
|
84
|
+
end
|
101
85
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
end
|
86
|
+
it "resets all double_injections" do
|
87
|
+
double_1 = space.double_injection(subject_1, method_name)
|
88
|
+
double_1_reset_calls = 0
|
89
|
+
(
|
90
|
+
class << double_1;
|
91
|
+
self;
|
92
|
+
end).class_eval do
|
93
|
+
define_method(:reset) do ||
|
94
|
+
double_1_reset_calls += 1
|
112
95
|
end
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
96
|
+
end
|
97
|
+
double_2 = space.double_injection(subject_2, method_name)
|
98
|
+
double_2_reset_calls = 0
|
99
|
+
(
|
100
|
+
class << double_2;
|
101
|
+
self;
|
102
|
+
end).class_eval do
|
103
|
+
define_method(:reset) do ||
|
104
|
+
double_2_reset_calls += 1
|
122
105
|
end
|
123
|
-
|
124
|
-
yield
|
125
|
-
double1_reset_calls.should == 1
|
126
|
-
double2_reset_calls.should == 1
|
127
106
|
end
|
107
|
+
|
108
|
+
rr_reset
|
109
|
+
double_1_reset_calls.should == 1
|
110
|
+
double_2_reset_calls.should == 1
|
128
111
|
end
|
129
112
|
end
|
130
113
|
end
|
131
|
-
|
132
|
-
|
133
114
|
end
|
134
115
|
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
|
2
|
+
|
3
|
+
module RR
|
4
|
+
module DoubleDefinitions
|
5
|
+
describe ChildDoubleDefinitionCreator do
|
6
|
+
attr_reader :parent_subject, :parent_double_definition_creator, :parent_double_definition, :child_double_definition_creator
|
7
|
+
it_should_behave_like "Swapped Space"
|
8
|
+
before(:each) do
|
9
|
+
@parent_subject = Object.new
|
10
|
+
@parent_double_definition_creator = DoubleDefinitionCreator.new
|
11
|
+
@parent_double_definition = DoubleDefinition.new(parent_double_definition_creator, parent_subject)
|
12
|
+
@child_double_definition_creator = ChildDoubleDefinitionCreator.new(parent_double_definition)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "Strategies::Verification definitions" do
|
16
|
+
describe "methods without !" do
|
17
|
+
attr_reader :child_subject
|
18
|
+
before do
|
19
|
+
@child_subject = Object.new
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#mock" do
|
23
|
+
context "when passed a subject" do
|
24
|
+
it "sets #parent_double_definition.implementation to a Proc returning the passed-in subject" do
|
25
|
+
parent_double_definition.implementation.should be_nil
|
26
|
+
child_double_definition_creator.mock(child_subject)
|
27
|
+
parent_double_definition.implementation.call.should == child_subject
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#stub" do
|
33
|
+
context "when passed a subject" do
|
34
|
+
it "sets #parent_double_definition.implementation to a Proc returning the passed-in subject" do
|
35
|
+
parent_double_definition.implementation.should be_nil
|
36
|
+
child_double_definition_creator.stub(child_subject)
|
37
|
+
parent_double_definition.implementation.call.should == child_subject
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#dont_allow" do
|
43
|
+
context "when passed a subject" do
|
44
|
+
it "sets #parent_double_definition.implementation to a Proc returning the passed-in subject" do
|
45
|
+
parent_double_definition.implementation.should be_nil
|
46
|
+
child_double_definition_creator.dont_allow(child_subject)
|
47
|
+
parent_double_definition.implementation.call.should == child_subject
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "methods with !" do
|
54
|
+
describe "#mock!" do
|
55
|
+
it "sets #parent_double_definition.implementation to a Proc returning the #subject" do
|
56
|
+
parent_double_definition.implementation.should be_nil
|
57
|
+
child_subject = child_double_definition_creator.mock!.__creator__.subject
|
58
|
+
parent_double_definition.implementation.call.should == child_subject
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#stub!" do
|
63
|
+
it "sets #parent_double_definition.implementation to a Proc returning the #subject" do
|
64
|
+
parent_double_definition.implementation.should be_nil
|
65
|
+
child_subject = child_double_definition_creator.stub!.__creator__.subject
|
66
|
+
parent_double_definition.implementation.call.should == child_subject
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#dont_allow!" do
|
71
|
+
it "sets #parent_double_definition.implementation to a Proc returning the #subject" do
|
72
|
+
parent_double_definition.implementation.should be_nil
|
73
|
+
child_subject = child_double_definition_creator.dont_allow!.__creator__.subject
|
74
|
+
parent_double_definition.implementation.call.should == child_subject
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "Strategies::Scope definitions" do
|
81
|
+
describe "methods without !" do
|
82
|
+
describe "#instance_of" do
|
83
|
+
it "raises a NoMethodError" do
|
84
|
+
lambda do
|
85
|
+
child_double_definition_creator.instance_of
|
86
|
+
end.should raise_error(NoMethodError)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "methods with !" do
|
92
|
+
describe "#instance_of!" do
|
93
|
+
it "raises a NoMethodError" do
|
94
|
+
lambda do
|
95
|
+
child_double_definition_creator.instance_of!
|
96
|
+
end.should raise_error(NoMethodError)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
|
2
|
+
|
3
|
+
module RR
|
4
|
+
module DoubleDefinitions
|
5
|
+
describe DoubleDefinitionCreatorProxy do
|
6
|
+
attr_reader :subject, :creator, :the_proxy
|
7
|
+
it_should_behave_like "Swapped Space"
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
@subject = Object.new
|
11
|
+
@creator = DoubleDefinitionCreator.new
|
12
|
+
creator.mock(subject)
|
13
|
+
end
|
14
|
+
|
15
|
+
macro("initializes proxy with passed in creator") do
|
16
|
+
it "initializes proxy with passed in creator" do
|
17
|
+
class << the_proxy
|
18
|
+
attr_reader :creator
|
19
|
+
end
|
20
|
+
the_proxy.creator.should === creator
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe ".new" do
|
25
|
+
it "does not undefine object_id" do
|
26
|
+
the_proxy = DoubleDefinitionCreatorProxy.new(creator)
|
27
|
+
the_proxy.object_id.class.should == Fixnum
|
28
|
+
end
|
29
|
+
|
30
|
+
context "without block" do
|
31
|
+
before do
|
32
|
+
@the_proxy = DoubleDefinitionCreatorProxy.new(creator)
|
33
|
+
end
|
34
|
+
|
35
|
+
send "initializes proxy with passed in creator"
|
36
|
+
|
37
|
+
it "clears out all methods from proxy" do
|
38
|
+
proxy_subclass = Class.new(DoubleDefinitionCreatorProxy) do
|
39
|
+
def i_should_be_a_double
|
40
|
+
end
|
41
|
+
end
|
42
|
+
proxy_subclass.instance_methods.map {|m| m.to_s}.should include('i_should_be_a_double')
|
43
|
+
|
44
|
+
proxy = proxy_subclass.new(creator)
|
45
|
+
proxy.i_should_be_a_double.should be_instance_of(DoubleDefinition)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "with block" do
|
50
|
+
before do
|
51
|
+
@the_proxy = DoubleDefinitionCreatorProxy.new(creator) do |b|
|
52
|
+
b.foobar(1, 2) {:one_two}
|
53
|
+
b.foobar(1) {:one}
|
54
|
+
b.foobar.with_any_args {:default}
|
55
|
+
b.baz() {:baz_result}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
send "initializes proxy with passed in creator"
|
60
|
+
|
61
|
+
it "creates double_injections" do
|
62
|
+
subject.foobar(1, 2).should == :one_two
|
63
|
+
subject.foobar(1).should == :one
|
64
|
+
subject.foobar(:something).should == :default
|
65
|
+
subject.baz.should == :baz_result
|
66
|
+
end
|
67
|
+
|
68
|
+
it "clears out all methods from proxy" do
|
69
|
+
proxy_subclass = Class.new(DoubleDefinitionCreatorProxy) do
|
70
|
+
def i_should_be_a_double
|
71
|
+
end
|
72
|
+
end
|
73
|
+
proxy_subclass.instance_methods.map {|m| m.to_s}.should include('i_should_be_a_double')
|
74
|
+
|
75
|
+
proxy_subclass.new(creator) do |m|
|
76
|
+
m.i_should_be_a_double.should be_instance_of(DoubleDefinition)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,495 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
|
2
|
+
|
3
|
+
module RR
|
4
|
+
module DoubleDefinitions
|
5
|
+
describe DoubleDefinitionCreator do
|
6
|
+
attr_reader :creator, :subject, :strategy_method_name
|
7
|
+
it_should_behave_like "Swapped Space"
|
8
|
+
before(:each) do
|
9
|
+
@subject = Object.new
|
10
|
+
@creator = DoubleDefinitionCreator.new
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "StrategySetupMethods" do
|
14
|
+
describe "normal strategy definitions" do
|
15
|
+
def call_strategy(*args, &block)
|
16
|
+
creator.__send__(strategy_method_name, *args, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#mock" do
|
20
|
+
before do
|
21
|
+
@strategy_method_name = :mock
|
22
|
+
end
|
23
|
+
|
24
|
+
send("normal strategy definition")
|
25
|
+
|
26
|
+
context "when passing no args" do
|
27
|
+
it "returns self" do
|
28
|
+
call_strategy.should === creator
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "when passed a subject and a method_name argument" do
|
33
|
+
it "creates a mock Double for method" do
|
34
|
+
double_definition = creator.mock(subject, :foobar).returns {:baz}
|
35
|
+
double_definition.times_matcher.should == TimesCalledMatchers::IntegerMatcher.new(1)
|
36
|
+
double_definition.argument_expectation.class.should == RR::Expectations::ArgumentEqualityExpectation
|
37
|
+
double_definition.argument_expectation.expected_arguments.should == []
|
38
|
+
subject.foobar.should == :baz
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when already using an ImplementationStrategy" do
|
43
|
+
it "raises a DoubleDefinitionError" do
|
44
|
+
creator.mock
|
45
|
+
lambda do
|
46
|
+
call_strategy
|
47
|
+
end.should raise_error(RR::Errors::DoubleDefinitionError, "This Double already has a mock strategy")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#stub" do
|
53
|
+
before do
|
54
|
+
@strategy_method_name = :stub
|
55
|
+
end
|
56
|
+
|
57
|
+
send("normal strategy definition")
|
58
|
+
|
59
|
+
context "when passing no args" do
|
60
|
+
it "returns self" do
|
61
|
+
call_strategy.should === creator
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when passed subject and a method_name argument" do
|
66
|
+
it "creates a stub Double for method when passed a method_name argument" do
|
67
|
+
double_definition = creator.stub(subject, :foobar).returns {:baz}
|
68
|
+
double_definition.times_matcher.should == TimesCalledMatchers::AnyTimesMatcher.new
|
69
|
+
double_definition.argument_expectation.class.should == RR::Expectations::AnyArgumentExpectation
|
70
|
+
subject.foobar.should == :baz
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "when already using an ImplementationStrategy" do
|
75
|
+
it "raises a DoubleDefinitionError" do
|
76
|
+
creator.mock
|
77
|
+
lambda do
|
78
|
+
call_strategy
|
79
|
+
end.should raise_error(RR::Errors::DoubleDefinitionError, "This Double already has a mock strategy")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "#dont_allow" do
|
85
|
+
before do
|
86
|
+
@strategy_method_name = :dont_allow
|
87
|
+
end
|
88
|
+
|
89
|
+
send("normal strategy definition")
|
90
|
+
|
91
|
+
context "when passing no args" do
|
92
|
+
it "returns self" do
|
93
|
+
call_strategy.should === creator
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
it "raises error when proxied" do
|
98
|
+
creator.proxy
|
99
|
+
lambda do
|
100
|
+
creator.dont_allow
|
101
|
+
end.should raise_error(Errors::DoubleDefinitionError, "Doubles cannot be proxied when using dont_allow strategy")
|
102
|
+
end
|
103
|
+
|
104
|
+
context "when passed a subject and a method_name argument_expectation" do
|
105
|
+
it "creates a mock Double for method" do
|
106
|
+
double_definition = creator.dont_allow(subject, :foobar)
|
107
|
+
double_definition.times_matcher.should == TimesCalledMatchers::IntegerMatcher.new(0)
|
108
|
+
double_definition.argument_expectation.class.should == RR::Expectations::AnyArgumentExpectation
|
109
|
+
|
110
|
+
lambda do
|
111
|
+
subject.foobar
|
112
|
+
end.should raise_error(Errors::TimesCalledError)
|
113
|
+
RR.reset
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context "when already using an ImplementationStrategy" do
|
118
|
+
it "raises a DoubleDefinitionError" do
|
119
|
+
creator.mock
|
120
|
+
lambda do
|
121
|
+
call_strategy
|
122
|
+
end.should raise_error(RR::Errors::DoubleDefinitionError, "This Double already has a mock strategy")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "! strategy definitions" do
|
129
|
+
attr_reader :strategy_method_name
|
130
|
+
def call_strategy(*args, &definition_eval_block)
|
131
|
+
creator.__send__(strategy_method_name, *args, &definition_eval_block)
|
132
|
+
end
|
133
|
+
|
134
|
+
describe "#mock!" do
|
135
|
+
before do
|
136
|
+
@strategy_method_name = :mock!
|
137
|
+
end
|
138
|
+
|
139
|
+
send("! strategy definition")
|
140
|
+
|
141
|
+
context "when passed a method_name argument" do
|
142
|
+
it "sets #verification_strategy to Mock" do
|
143
|
+
creator.mock!(:foobar)
|
144
|
+
creator.verification_strategy.class.should == Strategies::Verification::Mock
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "#stub!" do
|
150
|
+
before do
|
151
|
+
@strategy_method_name = :stub!
|
152
|
+
end
|
153
|
+
|
154
|
+
send("! strategy definition")
|
155
|
+
|
156
|
+
context "when passed a method_name argument" do
|
157
|
+
it "sets #verification_strategy to Stub" do
|
158
|
+
creator.stub!(:foobar)
|
159
|
+
creator.verification_strategy.class.should == Strategies::Verification::Stub
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "#dont_allow!" do
|
165
|
+
before do
|
166
|
+
@strategy_method_name = :dont_allow!
|
167
|
+
end
|
168
|
+
|
169
|
+
send("! strategy definition")
|
170
|
+
|
171
|
+
context "when passed a method_name argument" do
|
172
|
+
it "sets #verification_strategy to DontAllow" do
|
173
|
+
creator.dont_allow!(:foobar)
|
174
|
+
creator.verification_strategy.class.should == Strategies::Verification::DontAllow
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
describe "#stub.proxy" do
|
181
|
+
before do
|
182
|
+
class << subject
|
183
|
+
def foobar(*args)
|
184
|
+
:original_foobar
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context "when already using Strategies::Verification::DontAllow" do
|
190
|
+
it "raises error" do
|
191
|
+
creator.dont_allow
|
192
|
+
lambda do
|
193
|
+
creator.proxy
|
194
|
+
end.should raise_error(Errors::DoubleDefinitionError, "Doubles cannot be proxied when using dont_allow strategy")
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context "when passed a method_name argument" do
|
199
|
+
it "creates a proxy Double for method" do
|
200
|
+
double_definition = creator.stub.proxy(subject, :foobar).after_call {:baz}
|
201
|
+
double_definition.times_matcher.should == TimesCalledMatchers::AnyTimesMatcher.new
|
202
|
+
double_definition.argument_expectation.class.should == RR::Expectations::AnyArgumentExpectation
|
203
|
+
subject.foobar.should == :baz
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
describe "#instance_of" do
|
209
|
+
context "when not passed a class" do
|
210
|
+
it "raises an ArgumentError" do
|
211
|
+
lambda do
|
212
|
+
creator.instance_of(Object.new)
|
213
|
+
end.should raise_error(ArgumentError, "instance_of only accepts class objects")
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
context "when passed a method_name argument" do
|
218
|
+
it "creates a proxy Double for method" do
|
219
|
+
klass = Class.new
|
220
|
+
double_definition = creator.stub.instance_of(klass, :foobar).returns {:baz}
|
221
|
+
double_definition.times_matcher.should == TimesCalledMatchers::AnyTimesMatcher.new
|
222
|
+
double_definition.argument_expectation.class.should == RR::Expectations::AnyArgumentExpectation
|
223
|
+
klass.new.foobar.should == :baz
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe "#instance_of.mock" do
|
229
|
+
before do
|
230
|
+
@klass = Class.new
|
231
|
+
end
|
232
|
+
|
233
|
+
context "when passed no arguments" do
|
234
|
+
it "returns a DoubleDefinitionCreator" do
|
235
|
+
instance_of.instance_of.should be_instance_of(DoubleDefinitionCreator)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
context "when passed a method_name argument" do
|
240
|
+
it "creates a instance_of Double for method" do
|
241
|
+
double_definition = instance_of.mock(@klass, :foobar)
|
242
|
+
double_definition.with(1, 2) {:baz}
|
243
|
+
double_definition.times_matcher.should == TimesCalledMatchers::IntegerMatcher.new(1)
|
244
|
+
double_definition.argument_expectation.class.should == RR::Expectations::ArgumentEqualityExpectation
|
245
|
+
double_definition.argument_expectation.expected_arguments.should == [1, 2]
|
246
|
+
|
247
|
+
@klass.new.foobar(1, 2).should == :baz
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
describe "StrategyExecutionMethods" do
|
254
|
+
describe "#create" do
|
255
|
+
context "when #verification_strategy is not set" do
|
256
|
+
it "raises a DoubleDefinitionError" do
|
257
|
+
lambda do
|
258
|
+
creator.create(:foobar, 1, 2)
|
259
|
+
end.should raise_error(Errors::DoubleDefinitionError, "This Double has no strategy")
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
context "when #verification_strategy is a Mock" do
|
264
|
+
context "when #implementation_strategy is a Reimplementation" do
|
265
|
+
before do
|
266
|
+
creator.mock(subject)
|
267
|
+
end
|
268
|
+
|
269
|
+
it "sets expectation on the #subject that it will be sent the method_name once with the passed-in arguments" do
|
270
|
+
creator.create(:foobar, 1, 2)
|
271
|
+
subject.foobar(1, 2)
|
272
|
+
lambda {subject.foobar(1, 2)}.should raise_error(Errors::TimesCalledError)
|
273
|
+
end
|
274
|
+
|
275
|
+
describe "#subject.method_name being called" do
|
276
|
+
it "returns the return value of the Double#returns block" do
|
277
|
+
creator.create(:foobar, 1, 2) {:baz}
|
278
|
+
subject.foobar(1, 2).should == :baz
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context "when #implementation_strategy is a Proxy" do
|
284
|
+
before do
|
285
|
+
creator.mock
|
286
|
+
creator.proxy(subject)
|
287
|
+
end
|
288
|
+
|
289
|
+
it "sets expectation on the #subject that it will be sent the method_name once with the passed-in arguments" do
|
290
|
+
def subject.foobar(*args)
|
291
|
+
:baz;
|
292
|
+
end
|
293
|
+
creator.create(:foobar, 1, 2)
|
294
|
+
subject.foobar(1, 2)
|
295
|
+
lambda {subject.foobar(1, 2)}.should raise_error(Errors::TimesCalledError)
|
296
|
+
end
|
297
|
+
|
298
|
+
describe "#subject.method_name being called" do
|
299
|
+
it "calls the original method" do
|
300
|
+
original_method_called = false
|
301
|
+
(class << subject; self; end).class_eval do
|
302
|
+
define_method(:foobar) do |*args|
|
303
|
+
original_method_called = true
|
304
|
+
end
|
305
|
+
end
|
306
|
+
creator.create(:foobar, 1, 2)
|
307
|
+
subject.foobar(1, 2)
|
308
|
+
original_method_called.should be_true
|
309
|
+
end
|
310
|
+
|
311
|
+
context "when not passed a block" do
|
312
|
+
it "returns the value of the original method" do
|
313
|
+
def subject.foobar(*args)
|
314
|
+
:baz;
|
315
|
+
end
|
316
|
+
creator.create(:foobar, 1, 2)
|
317
|
+
subject.foobar(1, 2).should == :baz
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
context "when passed a block" do
|
322
|
+
attr_reader :real_value
|
323
|
+
before do
|
324
|
+
@real_value = real_value = Object.new
|
325
|
+
(class << subject; self; end).class_eval do
|
326
|
+
define_method(:foobar) {real_value}
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
it "calls the block with the return value of the original method" do
|
331
|
+
creator.create(:foobar, 1, 2) do |value|
|
332
|
+
mock(value).a_method {99}
|
333
|
+
value
|
334
|
+
end
|
335
|
+
subject.foobar(1, 2)
|
336
|
+
real_value.a_method.should == 99
|
337
|
+
end
|
338
|
+
|
339
|
+
it "returns the return value of the block" do
|
340
|
+
creator.create(:foobar, 1, 2) do |value|
|
341
|
+
:something_else
|
342
|
+
end
|
343
|
+
subject.foobar(1, 2).should == :something_else
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
context "when #verification_strategy is a Stub" do
|
351
|
+
context "when #implementation_strategy is a Reimplementation" do
|
352
|
+
before do
|
353
|
+
creator.stub(subject)
|
354
|
+
end
|
355
|
+
|
356
|
+
context "when not passed a block" do
|
357
|
+
it "returns nil" do
|
358
|
+
creator.create(:foobar)
|
359
|
+
subject.foobar.should be_nil
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
context "when passed a block" do
|
364
|
+
describe "#subject.method_name being called" do
|
365
|
+
it "returns the return value of the block" do
|
366
|
+
creator.create(:foobar) {:baz}
|
367
|
+
subject.foobar.should == :baz
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
context "when not passed args" do
|
373
|
+
describe "#subject.method_name being called with any arguments" do
|
374
|
+
it "invokes the implementation of the Stub" do
|
375
|
+
creator.create(:foobar) {:baz}
|
376
|
+
subject.foobar(1, 2).should == :baz
|
377
|
+
subject.foobar().should == :baz
|
378
|
+
subject.foobar([]).should == :baz
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
context "when passed args" do
|
384
|
+
describe "#subject.method_name being called with the passed-in arguments" do
|
385
|
+
it "invokes the implementation of the Stub" do
|
386
|
+
creator.create(:foobar, 1, 2) {:baz}
|
387
|
+
subject.foobar(1, 2).should == :baz
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
describe "#subject.method_name being called with different arguments" do
|
392
|
+
it "raises a DoubleNotFoundError" do
|
393
|
+
creator.create(:foobar, 1, 2) {:baz}
|
394
|
+
lambda do
|
395
|
+
subject.foobar
|
396
|
+
end.should raise_error(Errors::DoubleNotFoundError)
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
context "when #implementation_strategy is a Proxy" do
|
403
|
+
before do
|
404
|
+
def subject.foobar(*args)
|
405
|
+
:original_return_value
|
406
|
+
end
|
407
|
+
creator.stub
|
408
|
+
creator.proxy(subject)
|
409
|
+
end
|
410
|
+
|
411
|
+
context "when not passed a block" do
|
412
|
+
describe "#subject.method_name being called" do
|
413
|
+
it "invokes the original implementanion" do
|
414
|
+
creator.create(:foobar)
|
415
|
+
subject.foobar.should == :original_return_value
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
context "when passed a block" do
|
421
|
+
describe "#subject.method_name being called" do
|
422
|
+
it "invokes the original implementanion and invokes the block with the return value of the original implementanion" do
|
423
|
+
passed_in_value = nil
|
424
|
+
creator.create(:foobar) do |original_return_value|
|
425
|
+
passed_in_value = original_return_value
|
426
|
+
end
|
427
|
+
subject.foobar
|
428
|
+
passed_in_value.should == :original_return_value
|
429
|
+
end
|
430
|
+
|
431
|
+
it "returns the return value of the block" do
|
432
|
+
creator.create(:foobar) do |original_return_value|
|
433
|
+
:new_return_value
|
434
|
+
end
|
435
|
+
subject.foobar.should == :new_return_value
|
436
|
+
end
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
context "when passed args" do
|
441
|
+
describe "#subject.method_name being called with the passed-in arguments" do
|
442
|
+
it "invokes the implementation of the Stub" do
|
443
|
+
creator.create(:foobar, 1, 2) {:baz}
|
444
|
+
subject.foobar(1, 2).should == :baz
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
describe "#subject.method_name being called with different arguments" do
|
449
|
+
it "raises a DoubleNotFoundError" do
|
450
|
+
creator.create(:foobar, 1, 2) {:baz}
|
451
|
+
lambda do
|
452
|
+
subject.foobar
|
453
|
+
end.should raise_error(Errors::DoubleNotFoundError)
|
454
|
+
end
|
455
|
+
end
|
456
|
+
end
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
context "when #verification_strategy is a DontAllow" do
|
461
|
+
before do
|
462
|
+
creator.dont_allow(subject)
|
463
|
+
end
|
464
|
+
|
465
|
+
context "when not passed args" do
|
466
|
+
describe "#subject.method_name being called with any arguments" do
|
467
|
+
it "raises a TimesCalledError" do
|
468
|
+
creator.create(:foobar)
|
469
|
+
lambda {subject.foobar}.should raise_error(Errors::TimesCalledError)
|
470
|
+
lambda {subject.foobar(1, 2)}.should raise_error(Errors::TimesCalledError)
|
471
|
+
end
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
context "when passed args" do
|
476
|
+
describe "#subject.method_name being called with the passed-in arguments" do
|
477
|
+
it "raises a TimesCalledError" do
|
478
|
+
creator.create(:foobar, 1, 2)
|
479
|
+
lambda {subject.foobar(1, 2)}.should raise_error(Errors::TimesCalledError)
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
describe "#subject.method_name being called with different arguments" do
|
484
|
+
it "raises a DoubleNotFoundError" do
|
485
|
+
creator.create(:foobar, 1, 2)
|
486
|
+
lambda {subject.foobar()}.should raise_error(Errors::DoubleNotFoundError)
|
487
|
+
end
|
488
|
+
end
|
489
|
+
end
|
490
|
+
end
|
491
|
+
end
|
492
|
+
end
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end
|