rr 1.0.4 → 1.0.5.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +15 -0
  2. data/CHANGES.md +376 -0
  3. data/Gemfile +7 -10
  4. data/README.md +822 -0
  5. data/Rakefile +24 -78
  6. data/VERSION +1 -0
  7. data/lib/rr.rb +3 -0
  8. data/lib/rr/adapters/minitest.rb +6 -0
  9. data/lib/rr/adapters/rr_methods.rb +6 -10
  10. data/lib/rr/adapters/rspec.rb +3 -0
  11. data/lib/rr/adapters/rspec2.rb +30 -0
  12. data/lib/rr/adapters/test_unit.rb +2 -0
  13. data/lib/rr/double.rb +3 -2
  14. data/lib/rr/double_definitions/child_double_definition_create.rb +3 -2
  15. data/lib/rr/double_definitions/double_definition.rb +15 -13
  16. data/lib/rr/double_definitions/double_definition_create.rb +9 -5
  17. data/lib/rr/double_definitions/double_injections/any_instance_of.rb +3 -2
  18. data/lib/rr/double_definitions/strategies/strategy.rb +5 -4
  19. data/lib/rr/double_definitions/strategies/strategy_methods.rb +6 -8
  20. data/lib/rr/double_definitions/strategies/verification/mock.rb +3 -3
  21. data/lib/rr/double_matches.rb +2 -1
  22. data/lib/rr/expectations/argument_equality_expectation.rb +2 -2
  23. data/lib/rr/expectations/times_called_expectation.rb +2 -2
  24. data/lib/rr/injections/double_injection.rb +12 -11
  25. data/lib/rr/injections/injection.rb +2 -2
  26. data/lib/rr/injections/method_missing_injection.rb +21 -7
  27. data/lib/rr/injections/singleton_method_added_injection.rb +3 -1
  28. data/lib/rr/method_dispatches/base_method_dispatch.rb +1 -1
  29. data/lib/rr/method_dispatches/method_dispatch.rb +2 -1
  30. data/lib/rr/method_dispatches/method_missing_dispatch.rb +2 -1
  31. data/lib/rr/proc_from_block.rb +8 -4
  32. data/lib/rr/space.rb +3 -2
  33. data/lib/rr/times_called_matchers/times_called_matcher.rb +2 -2
  34. data/lib/rr/version.rb +5 -0
  35. data/lib/rr/wildcard_matchers/boolean.rb +2 -2
  36. data/spec/runner.rb +41 -0
  37. metadata +45 -133
  38. data/.gitignore +0 -10
  39. data/.runrc +0 -3
  40. data/.rvmrc +0 -2
  41. data/CHANGES +0 -266
  42. data/Gemfile.lock +0 -31
  43. data/README.rdoc +0 -392
  44. data/benchmarks/rr_benchmark.rb +0 -32
  45. data/benchmarks/rspec_benchmark.rb +0 -14
  46. data/doc/0.6.0.release.markdown +0 -81
  47. data/doc/todo.txt +0 -0
  48. data/introducting_rr.txt +0 -206
  49. data/rr.gemspec +0 -37
  50. data/spec/api/any_instance_of/all_instances_of_spec.rb +0 -12
  51. data/spec/api/any_instance_of/any_instance_of_spec.rb +0 -47
  52. data/spec/api/any_instance_of/instance_of_spec.rb +0 -12
  53. data/spec/api/dont_allow/dont_allow_after_stub_spec.rb +0 -14
  54. data/spec/api/mock/mock_spec.rb +0 -193
  55. data/spec/api/proxy/proxy_spec.rb +0 -86
  56. data/spec/api/spy/spy_spec.rb +0 -49
  57. data/spec/api/strong/strong_spec.rb +0 -87
  58. data/spec/api/stub/stub_spec.rb +0 -152
  59. data/spec/core_spec_suite.rb +0 -19
  60. data/spec/environment_fixture_setup.rb +0 -8
  61. data/spec/minitest_spec_suite.rb +0 -21
  62. data/spec/proc_from_block_spec.rb +0 -14
  63. data/spec/rr/adapters/rr_methods_argument_matcher_spec.rb +0 -67
  64. data/spec/rr/adapters/rr_methods_creator_spec.rb +0 -137
  65. data/spec/rr/adapters/rr_methods_space_spec.rb +0 -98
  66. data/spec/rr/adapters/rr_methods_spec_helper.rb +0 -11
  67. data/spec/rr/adapters/rr_methods_times_matcher_spec.rb +0 -13
  68. data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +0 -112
  69. data/spec/rr/double_definitions/double_definition_create_blank_slate_spec.rb +0 -91
  70. data/spec/rr/double_definitions/double_definition_create_spec.rb +0 -443
  71. data/spec/rr/double_injection/double_injection_spec.rb +0 -546
  72. data/spec/rr/double_injection/double_injection_verify_spec.rb +0 -29
  73. data/spec/rr/errors/rr_error_spec.rb +0 -67
  74. data/spec/rr/expectations/any_argument_expectation_spec.rb +0 -47
  75. data/spec/rr/expectations/anything_argument_equality_expectation_spec.rb +0 -14
  76. data/spec/rr/expectations/argument_equality_expectation_spec.rb +0 -135
  77. data/spec/rr/expectations/boolean_argument_equality_expectation_spec.rb +0 -34
  78. data/spec/rr/expectations/hash_including_argument_equality_expectation_spec.rb +0 -82
  79. data/spec/rr/expectations/hash_including_spec.rb +0 -17
  80. data/spec/rr/expectations/satisfy_argument_equality_expectation_spec.rb +0 -59
  81. data/spec/rr/expectations/satisfy_spec.rb +0 -14
  82. data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +0 -22
  83. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +0 -37
  84. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +0 -43
  85. data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +0 -15
  86. data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +0 -58
  87. data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +0 -35
  88. data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +0 -39
  89. data/spec/rr/minitest/minitest_integration_test.rb +0 -59
  90. data/spec/rr/minitest/test_helper.rb +0 -7
  91. data/spec/rr/rspec/invocation_matcher_spec.rb +0 -279
  92. data/spec/rr/rspec/rspec_adapter_spec.rb +0 -63
  93. data/spec/rr/rspec/rspec_backtrace_tweaking_spec.rb +0 -31
  94. data/spec/rr/rspec/rspec_backtrace_tweaking_spec_fixture.rb +0 -11
  95. data/spec/rr/rspec/rspec_usage_spec.rb +0 -86
  96. data/spec/rr/space/hash_with_object_id_key_spec.rb +0 -88
  97. data/spec/rr/space/space_spec.rb +0 -596
  98. data/spec/rr/test_unit/test_helper.rb +0 -7
  99. data/spec/rr/test_unit/test_unit_backtrace_test.rb +0 -36
  100. data/spec/rr/test_unit/test_unit_integration_test.rb +0 -59
  101. data/spec/rr/times_called_matchers/any_times_matcher_spec.rb +0 -47
  102. data/spec/rr/times_called_matchers/at_least_matcher_spec.rb +0 -55
  103. data/spec/rr/times_called_matchers/at_most_matcher_spec.rb +0 -70
  104. data/spec/rr/times_called_matchers/integer_matcher_spec.rb +0 -70
  105. data/spec/rr/times_called_matchers/proc_matcher_spec.rb +0 -55
  106. data/spec/rr/times_called_matchers/range_matcher_spec.rb +0 -76
  107. data/spec/rr/times_called_matchers/times_called_matcher_spec.rb +0 -118
  108. data/spec/rr/wildcard_matchers/anything_spec.rb +0 -24
  109. data/spec/rr/wildcard_matchers/boolean_spec.rb +0 -36
  110. data/spec/rr/wildcard_matchers/duck_type_spec.rb +0 -52
  111. data/spec/rr/wildcard_matchers/is_a_spec.rb +0 -32
  112. data/spec/rr/wildcard_matchers/numeric_spec.rb +0 -32
  113. data/spec/rr/wildcard_matchers/range_spec.rb +0 -35
  114. data/spec/rr/wildcard_matchers/regexp_spec.rb +0 -43
  115. data/spec/rr_spec.rb +0 -28
  116. data/spec/rspec_spec_suite.rb +0 -17
  117. data/spec/spec.opts +0 -10
  118. data/spec/spec_helper.rb +0 -41
  119. data/spec/spec_suite.rb +0 -54
  120. data/spec/spy_verification_spec.rb +0 -129
  121. data/spec/test_unit_spec_suite.rb +0 -21
@@ -1,14 +0,0 @@
1
- require "rubygems"
2
- require "spec/mocks"
3
- require "benchmark"
4
-
5
- o = Object.new
6
-
7
- Benchmark.bm do |x|
8
- x.report do
9
- 1000.times do
10
- o.should_receive(:foobar).and_return("baz")
11
- o.foobar
12
- end
13
- end
14
- end
@@ -1,81 +0,0 @@
1
- I'm pleased to announce the 0.6.0 version of RR. The [changes](http://github.com/btakita/rr/tree/master%2FCHANGES?raw=true) include:
2
-
3
- * Declaring Double subject objects without having to pass it in via the mock!, stub!, dont_allow!, instance_of!, and proxy! methods
4
- * Revised Double chaining API
5
- * satisfy matcher
6
- * hash_including matcher
7
-
8
- # Declaring Double Subjects (The bang methods)
9
-
10
- In previous versions of RR, you always needed to pass in the subject of the double. For example:
11
-
12
- subject = Object.new
13
- mock(subject).does_something {:and_returns_me}
14
- subject.does_something # :and_returns_me
15
-
16
- Now you can have RR automatically create the subject object for you by using the ! method:
17
-
18
- subject = mock!.does_something {:and_returns_me}.subject
19
- subject.does_something # :and_returns_me
20
-
21
- Now the bang methods by themselves don't really add a whole lot, but when used in the context of Double chaining, they become a powerful addition.
22
-
23
- # Double Chaining
24
-
25
- Nick Kallen presented the use case for Double chaining and contributed a patch for the 0.5.0 release of RR. It has proved useful and is now more fully incorporated into RR. Now you can pass in your subject or use the subject provided by RR by using the ! method. Here are some examples of Double Chaining:
26
-
27
- mock(subject).first(1) {mock(Object.new).second(2) {mock(Object.new).third(3) {4}}}
28
- subject.first(1).second(2).third(3) # 4
29
-
30
- mock(subject).first(1) {mock!.second(2) {mock!.third(3) {4}}}
31
- subject.first(1).second(2).third(3) # 4
32
-
33
- mock(subject).first(1).mock!.second(2).mock!.third(3) {4}
34
- subject.first(1).second(2).third(3) # 4
35
-
36
- Of course you have access to the proxy facilities:
37
-
38
- mock.proxy(User).find('1').mock.proxy!.children.mock.proxy!.find_all_by_group_id(10)
39
- User.find('1').children.find_all_by_group_id(10) # Makes verifications pass and returns the actual children
40
-
41
- You can also do branched Double chaining:
42
-
43
- mock(subject).first do
44
- mock! do |expect|
45
- expect.branch1.mock!.branch11 {11} # or expect.branch1 {mock!.branch11 {11}}
46
- expect.branch2.mock!.branch22 {22} # or expect.branch2 {mock!.branch22 {22}}
47
- end
48
- end
49
- o = subject.first
50
- o.branch1.branch11 # 11
51
- o.branch2.branch22 # 22
52
-
53
- # Satisfy Matcher
54
-
55
- Matthew O'Conner submitted a patch that added the satisfy matcher. This adds the ability to add arbitrary argument expectation matchers.
56
-
57
- mock(object).foobar(satisfy {|arg| arg.length == 2})
58
- object.foobar("xy")
59
-
60
-
61
- # Hash Including Matcher
62
-
63
- Matthew O'Conner also submitted a patch that added the hash_including matcher. This adds a convenient way to assert that the passed-in hash includes certain key/value pairs.
64
-
65
- mock(object).foobar(hash_including(:red => "#FF0000", :blue => "#0000FF"))
66
- object.foobar({:red => "#FF0000", :blue => "#0000FF", :green => "#00FF00"})
67
-
68
- # Mailing list
69
-
70
- RR has a mailing lists at:
71
-
72
- * [double-ruby-users@rubyforge.org](mailto:double-ruby-users@rubyforge.org)
73
- * [double-ruby-devel@rubyforge.org](mailto:double-ruby-devel@rubyforge.org)
74
-
75
- Also, RR's rubyforge page is at [http://rubyforge.org/projects/double-ruby](http://rubyforge.org/projects/double-ruby) and of course the github page is at [http://github.com/btakita/rr](http://github.com/btakita/rr).
76
-
77
- # Yes, and there is more to come
78
-
79
- There are many interesting ideas floating around. Joseph Wilk has been playing around with [adding Spies](http://github.com/JoeSniff/rr) into RR. I'm also thinking about adding Double validation scoping into RR. Also, I'm impressed by Mocha's warning of unused stubs. Josh Susser also proposed having a mode where a warning would occur if a mocked method is not implemented on the subject being mocked.
80
-
81
- If you have any feature requests, please send an email to the mailing list or add it to the rubyforge tracker.
data/doc/todo.txt DELETED
File without changes
data/introducting_rr.txt DELETED
@@ -1,206 +0,0 @@
1
- **Introducting RR**
2
-
3
- I'm pleased to introduce a new Test Double framework names RR, which is short for Double Ruby.
4
- A Test Double is [double description]. You can read more about test doubles at http://xunitpatterns.com/Test%20Double.html.
5
-
6
- RR supports the following constructs:
7
- * Mock
8
- * Stub
9
- * instance_of
10
- * Probe
11
-
12
- **Mock**
13
- <pre>
14
- real_user = User.new
15
- mock(User).find('2') {real_user}
16
- </pre>
17
-
18
- The previous example overrides the User.find method and returns real_user. It also sets an expectation
19
- that the find method will receive the argument '2' once.
20
-
21
- **Stub**
22
- <pre>
23
- user = User.new
24
- my_article = articles(:my_article)
25
- stub(user).can_edit?(my_article) {true}
26
- </pre>
27
-
28
- The previous example overrides can_edit?. When the method receives the article, it returns true.
29
-
30
- **instance_of**
31
- You can mock or stub instances of a class.
32
- <pre>
33
- stub.instance_of(User).can_edit?(my_article) {true}
34
- </pre>
35
-
36
- The previous example stubs the can_edit? method of any intstance of User.
37
-
38
- **Probe**
39
-
40
- A probe is a test double strategy that lets the real method implementation be called, and allows you
41
- to intercept the return value, and possibly inject you own replacement return value.
42
- <pre>
43
- my_article = articles(:my_article)
44
- mock.probe(User).find('2') do |real_user|
45
- stub.probe(real_user).can_edit?(my_article) {true}
46
- real_user
47
- end
48
- </pre>
49
-
50
- The previous example, lets the real User.find method call happen, and intercepts its return value inside
51
- of the block.
52
-
53
- The real_user's can_edit? method is then stubbed and probed to return true.
54
-
55
- **Thats nice, how is it useful?**
56
-
57
- As with any tool, Mocks and Stubs have limitations.
58
- For example, mocks alone do not verify that the mocked out method conforms to the real object's interface.
59
- Probes solve this issue.
60
-
61
- Adding a probe ensures that:
62
- * The method call to User.find is valid
63
- * The return value of User.find is available to validate and/or add test doubles to
64
- * The method call to real_user.can_edit? is valid
65
-
66
- **I don't use Mocks. Why should I care?**
67
-
68
- State based testing is often the simplest and most straightforward way to make assertions.
69
- However Interaction assertions can serve as good documentation of how your system fits together.
70
- Interaction tests can also aid you in making your tests easier to set up and removing coupling between tests.
71
-
72
- Lets compare the state and interaction testing approaches in the can edit article example for the
73
- ArticlesController#edit action:
74
-
75
- **State Based Example**
76
- <pre>
77
- user = users(:bob)
78
- login(user)
79
- my_article = articles(:my_article)
80
- user.can_edit?(my_article).should == false
81
-
82
- lambda do
83
- post :edit, :id => my_article.id, :body => "Hello everybody"
84
- end.should raise_error(SecurityTrangressionError)
85
- </pre>
86
-
87
- **Interaction Based Example**
88
- <pre>
89
- user = users(:bob)
90
- login(user)
91
- my_article = articles(:my_article)
92
- mock.probe(user).can_edit? {false}
93
-
94
- lambda do
95
- post :edit, :id => my_article.id, :body => "Hello everybody"
96
- end.should raise_error(SecurityTrangressionError)
97
- </pre>
98
-
99
- These two examples are interesting because they verify slight different things.
100
- The interaction example states that when can_edit? with @article is called and returns false, a SecurityTrangressionError
101
- is raised.
102
- The state example gives information that bob cannot edit the article, and from that one can infer that
103
- bob trying to edit the article will raise a SecurityTrangressionError.
104
-
105
- State based testing tends to be more coupling than interaction based testing.
106
- Note that coupling is not necessarily bad.
107
- The state based example has both interface, data, and knowledge coupling compared to the interaction based test:
108
- * Interface coupling - If can_edit? does not return false, there is an error.
109
- * Fixture Data coupling - If the fixture data changes, there is an error.
110
- * Knowledge coupling - The ArticleController test needs to know how can_edit? returns false
111
-
112
- Interface coupling is actually a good thing, because it verifies the User and ArticleController work
113
- together proberly. This sort of testing is functional or integration testing.
114
-
115
- The Data and Knowledge coupling are not desirable characteristics because they cause the
116
- developer to be concerned about another part of the system, which takes development time.
117
- It can also cause unwanted test failures when the global fixture data is changed or when a change
118
- occurs that makes the ArticleController's test setup logic incorrect.
119
-
120
- Martin Fowler also notes that interaction testing has coupling to the edit action's implementation,
121
- in that the interaction example states that User#can_edit? must be called for the test to pass.
122
- I've found that sometimes this is desirable and sometimes it is not desirable.
123
-
124
- The coupling to the implementation encourages more decomposition but it also makes
125
- causes brittleness because changing the edit action to call another method will cause
126
- the test to fail.
127
-
128
- I'm not proposing the right solution in this case, because it is dependent on
129
- your situation. One thing to consider is:
130
- * Do you have functional or integration tests for the failure case?
131
-
132
- Taking the desirable and undesirable coupling into account
133
-
134
- Here is a view example that renders counts:
135
-
136
- **State Based Example**
137
- <pre>
138
- user = users(:bob)
139
- user.articles.count.should == 5
140
- user.articles.comments.count.should == 15
141
- user.gold_stars.count.should == 0
142
-
143
- render :template => "users/show"
144
- response.body.should include("Articles Posted: 5")
145
- response.body.should include("Comments Received: 15")
146
- response.body.should include("Gold Stars Received: 0")
147
- </pre>
148
-
149
- **Interaction Based Example**
150
- <pre>
151
- user = User.new
152
- mock.probe(user.articles).count {5}
153
- mock.probe(user.articles.comments).count {15}
154
- mock.probe(user.gold_stars).count {80}
155
-
156
- render :template => "users/show"
157
- response.body.should include("Articles Posted: 5")
158
- response.body.should include("Comments Received: 15")
159
- response.body.should include("Gold Stars Received: 80")
160
- </pre>
161
-
162
- The same tradeoffs are present in this view example as in the ActiclesController example,
163
- but the values of each of the tradeoffs are different.
164
-
165
- State testing couplings:
166
- * Interface coupling - If count returns a non-number, there is an error.
167
- * Fixture Data coupling - If the fixture data changes, there is an error.
168
- * Knowledge coupling - There is no noticeable knowledge coupling.
169
-
170
- Interaction testing couplings:
171
- * Implementation coupling - If the way the count is determined changes, there is an error.
172
-
173
- In these examples, it is fair to expect the counts derived from the fixtures to change quite often.
174
- Decoupling the counts from your fixtures yields more of a benefit because the interaction based example
175
- will probably not need to be changed as often as the state based example.
176
-
177
- The interaction based example also provides the benefits of:
178
- * being faster because there is no database access
179
- * providing more focus because non-count user data is not important to this example (the interaction example
180
- ignores the user data while the state based approach includes the user data)
181
- * not requiring you to change the fixture data to provide add "Gold Stars Received" because having
182
- "Gold Stars Received: 0" is almost meaningless (It could easily be calling count on something else
183
- that returns 0)
184
-
185
- **State vs. Interaction Based testing?**
186
-
187
- The examples I provided favor or are neutral to interaction based testing.
188
- This does not mean all testing should be done with interaction testing.
189
- There are many situations where state based testing is more
190
- straightforward and no more coupled than an interaction based test.
191
-
192
- Please pick the right toolset for your situation.
193
- In the future, I will blog about different situations and the trade-offs of
194
- using a state based approach, and/or an interaction based approach.
195
-
196
- **Extremely Bad Examples**
197
-
198
- Since this is a blog post, the examples are short and relatively benign.
199
- However, There are many examples where state and/or interaction
200
- based testing is overused and abused.
201
- Expanding your toolset can help you and your coworkers fix these issues.
202
-
203
- There are already several nice Mock/Stub frameworks in the ruby world. These libraries include:
204
- * Mocha
205
- * Flexmock
206
- * Rspec's Mock Framework
data/rr.gemspec DELETED
@@ -1,37 +0,0 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
5
-
6
- Gem::Specification.new do |s|
7
- s.name = %q{rr}
8
- s.version = "1.0.4"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Brian Takita"]
12
- s.date = %q{2011-06-16}
13
- s.description = %q{RR (Double Ruby) is a double framework that features a rich selection of double techniques and a terse syntax. http://xunitpatterns.com/Test%20Double.html}
14
- s.email = %q{brian@pivotallabs.com}
15
- s.extra_rdoc_files = [
16
- "CHANGES",
17
- "README.rdoc"
18
- ]
19
- s.files = `git ls-files`.split("\n")
20
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
- s.homepage = %q{http://pivotallabs.com}
22
- s.rdoc_options = ["--main", "README.rdoc", "--inline-source", "--line-numbers"]
23
- s.require_paths = ["lib"]
24
- s.rubyforge_project = %q{pivotalrb}
25
- s.rubygems_version = %q{1.6.2}
26
- s.summary = %q{RR (Double Ruby) is a double framework that features a rich selection of double techniques and a terse syntax. http://xunitpatterns.com/Test%20Double.html}
27
-
28
- if s.respond_to? :specification_version then
29
- s.specification_version = 3
30
-
31
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
32
- else
33
- end
34
- else
35
- end
36
- end
37
-
@@ -1,12 +0,0 @@
1
- require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
-
3
- describe "all_instances_of" do
4
- it "applies to instances instantiated before the Double expection was created" do
5
- subject_class = Class.new
6
- subject = subject_class.new
7
- all_instances_of(subject_class) do |o|
8
- o.to_s {"Subject is stubbed"}
9
- end
10
- subject.to_s.should == "Subject is stubbed"
11
- end
12
- end
@@ -1,47 +0,0 @@
1
- require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
-
3
- describe "any_instance_of" do
4
- context "when passed a block" do
5
- it "applies to instances instantiated before the Double expection was created" do
6
- subject_class = Class.new
7
- subject = subject_class.new
8
- class_called = false
9
- any_instance_of(subject_class) do |o|
10
- stub(o).to_s {"Subject is stubbed"}
11
- stub.proxy(o).class {|klass| class_called = true; klass}
12
- stub(o).foobar {:baz}
13
- end
14
-
15
- subject.to_s.should == "Subject is stubbed"
16
- subject.class.should == subject_class
17
- class_called.should == true
18
- subject.foobar.should == :baz
19
-
20
- RR.reset
21
-
22
- subject.to_s.should_not == "Subject is stubbed"
23
- class_called = false
24
- subject.class.should == subject_class
25
- class_called.should == false
26
- subject.should_not respond_to(:baz)
27
- end
28
- end
29
-
30
- context "when passed a Hash" do
31
- it "stubs methods (key) with the value on instances instantiated before the Double expection was created" do
32
- subject_class = Class.new
33
- subject = subject_class.new
34
- subject.should_not respond_to(:baz)
35
-
36
- any_instance_of(subject_class, :to_s => "Subject is stubbed", :foobar => lambda {:baz})
37
-
38
- subject.to_s.should == "Subject is stubbed"
39
- subject.foobar.should == :baz
40
-
41
- RR.reset
42
-
43
- subject.to_s.should_not == "Subject is stubbed"
44
- subject.should_not respond_to(:baz)
45
- end
46
- end
47
- end
@@ -1,12 +0,0 @@
1
- require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
-
3
- describe "instance_of" do
4
- it "applies to instances instantiated before the Double expection was created" do
5
- subject_class = Class.new
6
- subject = subject_class.new
7
- instance_of(subject_class) do |o|
8
- o.to_s {"Subject is stubbed"}
9
- end
10
- subject.to_s.should == "Subject is stubbed"
11
- end
12
- end
@@ -1,14 +0,0 @@
1
- require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
-
3
- describe "dont_allow called after stub" do
4
- context "when the subject method is called" do
5
- it "raises a TimesCalledError" do
6
- subject = Object.new
7
- stub(subject).foobar
8
- dont_allow(subject).foobar
9
- lambda do
10
- subject.foobar
11
- end.should raise_error(RR::Errors::TimesCalledError)
12
- end
13
- end
14
- end
@@ -1,193 +0,0 @@
1
- require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
-
3
- describe "mock" do
4
- attr_reader :subject
5
- before(:each) do
6
- @subject = Object.new
7
- extend RR::Adapters::RRMethods
8
- end
9
-
10
- after(:each) do
11
- RR.reset
12
- end
13
-
14
- it "mocks via inline call" do
15
- mock(subject).to_s {"a value"}
16
- subject.to_s.should == "a value"
17
- lambda {subject.to_s}.should raise_error(RR::Errors::TimesCalledError)
18
- end
19
-
20
- describe ".once.ordered" do
21
- it "returns the values in the ordered called" do
22
- mock(subject).to_s {"value 1"}.ordered
23
- mock(subject).to_s {"value 2"}.twice
24
- subject.to_s.should == "value 1"
25
- subject.to_s.should == "value 2"
26
- subject.to_s.should == "value 2"
27
- lambda {subject.to_s}.should raise_error(RR::Errors::TimesCalledError)
28
- end
29
- end
30
-
31
- context "when the subject is a proxy for the object with the defined method" do
32
- it "stubs the method on the proxy object" do
33
- proxy_target = Class.new {def foobar; :original_foobar; end}.new
34
- proxy = Class.new do
35
- def initialize(target)
36
- @target = target
37
- end
38
-
39
- instance_methods.each do |m|
40
- unless m =~ /^_/ || m.to_s == 'object_id' || m.to_s == 'method_missing'
41
- alias_method "__blank_slated_#{m}", m
42
- undef_method m
43
- end
44
- end
45
-
46
- def method_missing(method_name, *args, &block)
47
- @target.send(method_name, *args, &block)
48
- end
49
- end.new(proxy_target)
50
- proxy.methods.should =~ proxy_target.methods
51
-
52
- mock(proxy).foobar {:new_foobar}
53
- proxy.foobar.should == :new_foobar
54
- end
55
- end
56
-
57
- it 'allows terse chaining' do
58
- mock(subject).first(1) {mock(Object.new).second(2) {mock(Object.new).third(3) {4}}}
59
- subject.first(1).second(2).third(3).should == 4
60
-
61
- mock(subject).first(1) {mock!.second(2) {mock!.third(3) {4}}}
62
- subject.first(1).second(2).third(3).should == 4
63
-
64
- mock(subject).first(1) {mock!.second(2).mock!.third(3) {4}}
65
- subject.first(1).second(2).third(3).should == 4
66
-
67
- mock(subject).first(1) {mock!.second(2).mock! {third(3) {4}}}
68
- subject.first(1).second(2).third(3).should == 4
69
-
70
- mock(subject).first(1).mock!.second(2).mock!.third(3) {4}
71
- subject.first(1).second(2).third(3).should == 4
72
- end
73
-
74
- it 'allows chaining with proxy' do
75
- find_return_value = Object.new
76
- def find_return_value.child
77
- :the_child
78
- end
79
- (class << subject; self; end).class_eval do
80
- define_method(:find) do |id|
81
- id == '1' ? find_return_value : raise(ArgumentError)
82
- end
83
- end
84
-
85
- mock.proxy(subject).find('1').mock.proxy!.child
86
- subject.find('1').child.should == :the_child
87
- end
88
-
89
- it 'allows branched chaining' do
90
- mock(subject).first do
91
- mock! do |expect|
92
- expect.branch1 {mock!.branch11 {11}}
93
- expect.branch2 {mock!.branch22 {22}}
94
- end
95
- end
96
- o = subject.first
97
- o.branch1.branch11.should == 11
98
- o.branch2.branch22.should == 22
99
- end
100
-
101
- it 'allows chained ordering' do
102
- mock(subject).to_s {"value 1"}.then.to_s {"value 2"}.twice.then.to_s {"value 3"}.once
103
- subject.to_s.should == "value 1"
104
- subject.to_s.should == "value 2"
105
- subject.to_s.should == "value 2"
106
- subject.to_s.should == "value 3"
107
- lambda {subject.to_s}.should raise_error(RR::Errors::TimesCalledError)
108
- end
109
-
110
- it "mocks via block with argument" do
111
- mock subject do |c|
112
- c.to_s {"a value"}
113
- c.to_sym {:crazy}
114
- end
115
- subject.to_s.should == "a value"
116
- subject.to_sym.should == :crazy
117
- end
118
-
119
- it "mocks via block without argument" do
120
- mock subject do
121
- to_s {"a value"}
122
- to_sym {:crazy}
123
- end
124
- subject.to_s.should == "a value"
125
- subject.to_sym.should == :crazy
126
- end
127
-
128
- it "has wildcard matchers" do
129
- mock(subject).foobar(
130
- is_a(String),
131
- anything,
132
- numeric,
133
- boolean,
134
- duck_type(:to_s),
135
- /abc/
136
- ) {"value 1"}.twice
137
- subject.foobar(
138
- 'hello',
139
- Object.new,
140
- 99,
141
- false,
142
- "My String",
143
- "Tabcola"
144
- ).should == "value 1"
145
- lambda do
146
- subject.foobar(:failure)
147
- end.should raise_error( RR::Errors::DoubleNotFoundError )
148
- end
149
-
150
- it "mocks methods without letters" do
151
- mock(subject, :==).with(55)
152
-
153
- subject == 55
154
- lambda do
155
- subject == 99
156
- end.should raise_error(RR::Errors::DoubleNotFoundError)
157
- end
158
-
159
- it "expects a method call to a mock via another mock's block yield only once" do
160
- cage = Object.new
161
- cat = Object.new
162
- mock(cat).miau # should be expected to be called only once
163
- mock(cage).find_cat.yields(cat)
164
- mock(cage).cats
165
- cage.find_cat { |c| c.miau }
166
- cage.cats
167
- end
168
-
169
- describe "on class method" do
170
- class SampleClass1
171
- def self.hello; "hello!"; end
172
- end
173
-
174
- class SampleClass2 < SampleClass1; end
175
-
176
- it "can mock" do
177
- mock(SampleClass1).hello { "hola!" }
178
-
179
- SampleClass1.hello.should == "hola!"
180
- end
181
-
182
- it "does not override subclasses" do
183
- mock(SampleClass1).hello { "hi!" }
184
-
185
- SampleClass2.hello.should == "hello!"
186
- end
187
-
188
- it "should not get affected from a previous example" do
189
- SampleClass2.hello.should == "hello!"
190
- end
191
-
192
- end
193
- end