rr 1.1.1.rc1 → 1.1.1

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.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/CREDITS.md +61 -0
  3. data/VERSION +1 -1
  4. data/doc/01_test_double.md +16 -0
  5. data/doc/02_syntax_comparison.md +96 -0
  6. data/doc/03_api_overview.md +616 -0
  7. data/rr.gemspec +6 -6
  8. metadata +12 -230
  9. data/spec/global_helper.rb +0 -53
  10. data/spec/spec.opts +0 -2
  11. data/spec/suite.rb +0 -107
  12. data/spec/suites/common/adapter_integration_tests.rb +0 -160
  13. data/spec/suites/common/adapter_tests.rb +0 -43
  14. data/spec/suites/common/rails_integration_tests.rb +0 -106
  15. data/spec/suites/common/test_unit_tests.rb +0 -21
  16. data/spec/suites/minitest/integration/minitest_test.rb +0 -13
  17. data/spec/suites/minitest/test_helper.rb +0 -7
  18. data/spec/suites/minitest_4/integration/minitest_test.rb +0 -13
  19. data/spec/suites/minitest_4/test_helper.rb +0 -7
  20. data/spec/suites/rspec_1/helper.rb +0 -24
  21. data/spec/suites/rspec_1/integration/rspec_1_spec.rb +0 -77
  22. data/spec/suites/rspec_1/integration/test_unit_1_spec.rb +0 -41
  23. data/spec/suites/rspec_1/integration/test_unit_2_spec.rb +0 -57
  24. data/spec/suites/rspec_1/spec_helper.rb +0 -3
  25. data/spec/suites/rspec_1_rails_2/integration/test_unit_1_rails_2_spec.rb +0 -53
  26. data/spec/suites/rspec_1_rails_2/integration/test_unit_2_rails_2_spec.rb +0 -57
  27. data/spec/suites/rspec_1_rails_2/spec_helper.rb +0 -3
  28. data/spec/suites/rspec_2/functional/any_instance_of_spec.rb +0 -47
  29. data/spec/suites/rspec_2/functional/dont_allow_spec.rb +0 -12
  30. data/spec/suites/rspec_2/functional/dsl_spec.rb +0 -13
  31. data/spec/suites/rspec_2/functional/instance_of_spec.rb +0 -14
  32. data/spec/suites/rspec_2/functional/mock_spec.rb +0 -241
  33. data/spec/suites/rspec_2/functional/proxy_spec.rb +0 -136
  34. data/spec/suites/rspec_2/functional/spy_spec.rb +0 -41
  35. data/spec/suites/rspec_2/functional/strong_spec.rb +0 -79
  36. data/spec/suites/rspec_2/functional/stub_spec.rb +0 -190
  37. data/spec/suites/rspec_2/functional/wildcard_matchers_spec.rb +0 -128
  38. data/spec/suites/rspec_2/helper.rb +0 -27
  39. data/spec/suites/rspec_2/integration/minitest_4_spec.rb +0 -57
  40. data/spec/suites/rspec_2/integration/minitest_spec.rb +0 -57
  41. data/spec/suites/rspec_2/integration/rspec_2_spec.rb +0 -126
  42. data/spec/suites/rspec_2/integration/test_unit_200_spec.rb +0 -57
  43. data/spec/suites/rspec_2/integration/test_unit_2_spec.rb +0 -57
  44. data/spec/suites/rspec_2/spec_helper.rb +0 -3
  45. data/spec/suites/rspec_2/support/matchers/wildcard_matcher_matchers.rb +0 -32
  46. data/spec/suites/rspec_2/support/shared_examples/space.rb +0 -13
  47. data/spec/suites/rspec_2/support/shared_examples/times_called_expectation.rb +0 -9
  48. data/spec/suites/rspec_2/unit/adapters/rr_methods/double_creators_spec.rb +0 -135
  49. data/spec/suites/rspec_2/unit/adapters/rr_methods/space_spec.rb +0 -101
  50. data/spec/suites/rspec_2/unit/adapters/rr_methods/wildcard_matchers_spec.rb +0 -69
  51. data/spec/suites/rspec_2/unit/core_ext/array_spec.rb +0 -39
  52. data/spec/suites/rspec_2/unit/core_ext/enumerable_spec.rb +0 -81
  53. data/spec/suites/rspec_2/unit/core_ext/hash_spec.rb +0 -55
  54. data/spec/suites/rspec_2/unit/core_ext/range_spec.rb +0 -41
  55. data/spec/suites/rspec_2/unit/core_ext/regexp_spec.rb +0 -41
  56. data/spec/suites/rspec_2/unit/double_definitions/child_double_definition_create_spec.rb +0 -114
  57. data/spec/suites/rspec_2/unit/double_definitions/double_definition_create_blank_slate_spec.rb +0 -93
  58. data/spec/suites/rspec_2/unit/double_definitions/double_definition_create_spec.rb +0 -446
  59. data/spec/suites/rspec_2/unit/errors/rr_error_spec.rb +0 -67
  60. data/spec/suites/rspec_2/unit/expectations/any_argument_expectation_spec.rb +0 -48
  61. data/spec/suites/rspec_2/unit/expectations/anything_argument_equality_expectation_spec.rb +0 -14
  62. data/spec/suites/rspec_2/unit/expectations/argument_equality_expectation_spec.rb +0 -135
  63. data/spec/suites/rspec_2/unit/expectations/boolean_argument_equality_expectation_spec.rb +0 -30
  64. data/spec/suites/rspec_2/unit/expectations/hash_including_argument_equality_expectation_spec.rb +0 -82
  65. data/spec/suites/rspec_2/unit/expectations/satisfy_argument_equality_expectation_spec.rb +0 -61
  66. data/spec/suites/rspec_2/unit/expectations/times_called_expectation/any_times_matcher_spec.rb +0 -22
  67. data/spec/suites/rspec_2/unit/expectations/times_called_expectation/at_least_matcher_spec.rb +0 -37
  68. data/spec/suites/rspec_2/unit/expectations/times_called_expectation/at_most_matcher_spec.rb +0 -43
  69. data/spec/suites/rspec_2/unit/expectations/times_called_expectation/integer_matcher_spec.rb +0 -58
  70. data/spec/suites/rspec_2/unit/expectations/times_called_expectation/proc_matcher_spec.rb +0 -35
  71. data/spec/suites/rspec_2/unit/expectations/times_called_expectation/range_matcher_spec.rb +0 -39
  72. data/spec/suites/rspec_2/unit/hash_with_object_id_key_spec.rb +0 -88
  73. data/spec/suites/rspec_2/unit/injections/double_injection/double_injection_spec.rb +0 -545
  74. data/spec/suites/rspec_2/unit/injections/double_injection/double_injection_verify_spec.rb +0 -32
  75. data/spec/suites/rspec_2/unit/integrations/rspec/invocation_matcher_spec.rb +0 -297
  76. data/spec/suites/rspec_2/unit/integrations/rspec_spec.rb +0 -85
  77. data/spec/suites/rspec_2/unit/proc_from_block_spec.rb +0 -14
  78. data/spec/suites/rspec_2/unit/rr_spec.rb +0 -28
  79. data/spec/suites/rspec_2/unit/space_spec.rb +0 -595
  80. data/spec/suites/rspec_2/unit/spy_verification_spec.rb +0 -133
  81. data/spec/suites/rspec_2/unit/times_called_matchers/any_times_matcher_spec.rb +0 -46
  82. data/spec/suites/rspec_2/unit/times_called_matchers/at_least_matcher_spec.rb +0 -54
  83. data/spec/suites/rspec_2/unit/times_called_matchers/at_most_matcher_spec.rb +0 -69
  84. data/spec/suites/rspec_2/unit/times_called_matchers/integer_matcher_spec.rb +0 -69
  85. data/spec/suites/rspec_2/unit/times_called_matchers/proc_matcher_spec.rb +0 -54
  86. data/spec/suites/rspec_2/unit/times_called_matchers/range_matcher_spec.rb +0 -75
  87. data/spec/suites/rspec_2/unit/times_called_matchers/times_called_matcher_spec.rb +0 -117
  88. data/spec/suites/rspec_2/unit/wildcard_matchers/anything_spec.rb +0 -33
  89. data/spec/suites/rspec_2/unit/wildcard_matchers/boolean_spec.rb +0 -45
  90. data/spec/suites/rspec_2/unit/wildcard_matchers/duck_type_spec.rb +0 -64
  91. data/spec/suites/rspec_2/unit/wildcard_matchers/hash_including_spec.rb +0 -64
  92. data/spec/suites/rspec_2/unit/wildcard_matchers/is_a_spec.rb +0 -55
  93. data/spec/suites/rspec_2/unit/wildcard_matchers/numeric_spec.rb +0 -46
  94. data/spec/suites/rspec_2/unit/wildcard_matchers/satisfy_spec.rb +0 -57
  95. data/spec/suites/rspec_2_rails_3/integration/minitest_4_rails_3_spec.rb +0 -66
  96. data/spec/suites/rspec_2_rails_3/integration/test_unit_200_rails_3_spec.rb +0 -66
  97. data/spec/suites/rspec_2_rails_3/integration/test_unit_2_rails_3_spec.rb +0 -66
  98. data/spec/suites/rspec_2_rails_3/spec_helper.rb +0 -3
  99. data/spec/suites/rspec_2_rails_4/integration/minitest_4_rails_4_spec.rb +0 -66
  100. data/spec/suites/rspec_2_rails_4/integration/rspec_2_rails_4_spec.rb +0 -156
  101. data/spec/suites/rspec_2_rails_4/integration/test_unit_200_rails_4_spec.rb +0 -66
  102. data/spec/suites/rspec_2_rails_4/integration/test_unit_2_rails_4_spec.rb +0 -66
  103. data/spec/suites/rspec_2_rails_4/spec_helper.rb +0 -3
  104. data/spec/suites/test_unit_1/integration/test_unit_1_test.rb +0 -10
  105. data/spec/suites/test_unit_1/test_helper.rb +0 -10
  106. data/spec/suites/test_unit_2/integration/test_unit_2_test.rb +0 -10
  107. data/spec/suites/test_unit_2/test_helper.rb +0 -6
  108. data/spec/suites/test_unit_200/integration/test_unit_200_test.rb +0 -10
  109. data/spec/suites/test_unit_200/test_helper.rb +0 -6
  110. data/spec/suites/test_unit_200_rails_3/integration/test_unit_200_rails_3_test.rb +0 -10
  111. data/spec/suites/test_unit_200_rails_3/test_helper.rb +0 -7
  112. data/spec/suites/test_unit_200_rails_4/integration/test_unit_200_rails_4_test.rb +0 -10
  113. data/spec/suites/test_unit_200_rails_4/test_helper.rb +0 -7
  114. data/spec/suites/test_unit_2_rails_2/integration/test_unit_2_rails_2_test.rb +0 -10
  115. data/spec/suites/test_unit_2_rails_2/test_helper.rb +0 -7
  116. data/spec/suites/test_unit_2_rails_3/integration/test_unit_2_rails_3_test.rb +0 -10
  117. data/spec/suites/test_unit_2_rails_3/test_helper.rb +0 -7
  118. data/spec/suites/test_unit_2_rails_4/integration/test_unit_2_rails_4_test.rb +0 -10
  119. data/spec/suites/test_unit_2_rails_4/test_helper.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a584672b5a5ce3c3c03093ce18e53fbbfadfa346
4
- data.tar.gz: fc6f53501f6fb256fe532ce42ee656785271f616
3
+ metadata.gz: ba1e0b3ea37112b713b116b3f42156d3d0269717
4
+ data.tar.gz: 3e933262c2d9a50a495497067508d154e1d9ec9b
5
5
  SHA512:
6
- metadata.gz: 2b046b021e0a98b897d2fc9ad9aa1ea7dd4f07ce1bd309f5939bf17ecfad2e43469427b0698bbc38a0e257988bd088ea77f9d3b8a1f24758c8a6f214ce91d830
7
- data.tar.gz: e1bcb162b15baa2873f48973f6ec621c0df9c3eac885ada650d6aaadfc93957ffc4197baf605a08dd82f273667298a77970e93f88133e6f3f4d0a604029a9f56
6
+ metadata.gz: 92301ad0c0e78016f5c10ca7c406a19612398a45b595892de2912159fd2b878ceaecf57b02a043332b5e086d0f45ab618989b79d501d1ad8b90982ff5469a1f7
7
+ data.tar.gz: 0109fbc48ec0aac6ae07f3fecb9af272311c73deeaae702c61b705beb7429f5fb367406d8475b12ebb918f09840bb70ce0e430034958b8861f0674ab10bb4b71
@@ -0,0 +1,61 @@
1
+ # Credits
2
+
3
+ ## Authors
4
+
5
+ * Brian Takita ([@btakita](http://github.com/btakita))
6
+ * Elliot Winkler ([@mcmire](http://github.com/mcmire))
7
+
8
+
9
+ ## Contributors
10
+
11
+ * Andreas Haller ([@ahx](http://github.com/ahx))
12
+ * Bryan Helmkamp ([@brynary](http://github.com/brynary))
13
+ * [@bonkydog](http://github.com/bonkydog)
14
+ * Caleb Spare ([@cespare](http://github.com/cespare))
15
+ * Christopher Redinger ([@redinger](http://github.com/redinger))
16
+ * David Chelimsky ([@dchelimsky](http://github.com/dchelimsky))
17
+ * David Padilla ([@dabit](http://github.com/dabit))
18
+ * Dmitry Ratnikov ([@ratnikov](http://github.com/ratnikov))
19
+ * Eugene Pimenov ([@libc](http://github.com/libc))
20
+ * Evan Phoenix ([@evanphx](http://github.com/evanphx))
21
+ * Gabriel Horner ([@cldwalker](http://github.com/cldwalker))
22
+ * Gavin Miller ([@gavingmiller](http://github.com/gavingmiller))
23
+ * James McCarthy ([@james2m](http://github.com/james2m))
24
+ * Jan Nelson
25
+ * Jay Adkisson ([@jayferd](http://github.com/jayferd))
26
+ * Joe Ferris ([@jferris](http://github.com/jferris))
27
+ * Matt Buck ([@techpeace](http://github.com/techpeace))
28
+ * Matthew O'Connor
29
+ * Michael Niessner ([@niessner](http://github.com/niessner))
30
+ * Mike Mangino ([@mmangino](http://github.com/mmangino))
31
+ * Nathan Sobo ([@nathansobo](http://github.com/nathansobo))
32
+ * Nick Kallen ([@nkallen](http://github.com/nkallen))
33
+ * Nick Novitski ([@nicknovitski](http://github.com/nicknovitski))
34
+ * Phil Darnowsky ([@phildarnowsky](http://github.com/phildarnowsky))
35
+ * Steven R. Baker ([@srbaker](http://github.com/srbaker))
36
+ * Tatsuya Ono ([@ono](http://github.com/ono))
37
+ * Thibaut Corouble ([@thibaut](http://github.com/thibaut))
38
+ * Wincent Colaiuta ([@wincent](http://github.com/wincent))
39
+ * [@wynst](http://github.com/wynst)
40
+
41
+
42
+ ## Honorable mentions
43
+
44
+ * Aslak Hellesoy for developing RSpec
45
+ * Dan North for syntax ideas
46
+ * Dave Astels for some BDD inspiration
47
+ * Dave Myron for a bug report
48
+ * David Chelimsky for encouragement to make the RR framework, for developing the
49
+ RSpec mock framework, syntax ideas, and patches
50
+ * Daniel Sudol for identifing performance issues with RR
51
+ * Gerard Meszaros for his excellent book "xUnit Test Patterns"
52
+ * Felix Morio for pairing
53
+ * James Mead for developing Mocha
54
+ * Jeff Whitmire for documentation suggestions
55
+ * Jim Weirich for developing Flexmock, the first terse ruby mock framework in
56
+ Ruby
57
+ * Myron Marston for bug reports
58
+ * Parker Thompson for pairing
59
+ * Pivotal Labs for sponsoring RR development
60
+ * Steven Baker for developing RSpec
61
+ * Tuomas Kareinen for a bug report
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.1.rc1
1
+ 1.1.1
@@ -0,0 +1,16 @@
1
+ # What is a test double?
2
+
3
+ A test double is a generalization of something that replaces a real object to
4
+ make it easier to test another object. It's like a stunt double for tests. The
5
+ following are test doubles:
6
+
7
+ * Mocks
8
+ * Stubs
9
+ * Fakes
10
+ * Spies
11
+ * Proxies
12
+
13
+ *Learn more: <http://xunitpatterns.com/Test%20Double.html>*
14
+
15
+ Currently RR implements mocks, stubs, proxies, and spies. Fakes usually require
16
+ custom code, so it is beyond the scope of RR.
@@ -0,0 +1,96 @@
1
+ # Syntax between RR and other double/mock frameworks
2
+
3
+ ## Terse syntax
4
+
5
+ One of the goals of RR is to make doubles more scannable. This is accomplished
6
+ by making the double declaration look as much as the actual method invocation as
7
+ possible. Here is RR compared to other mock frameworks:
8
+
9
+ ~~~ ruby
10
+ # Flexmock
11
+ flexmock(User).should_receive(:find).with('42').and_return(jane)
12
+ # Mocha
13
+ User.expects(:find).with('42').returns { jane }
14
+ # rspec-mocks
15
+ User.should_receive(:find).with('42') { jane }
16
+ # RR
17
+ mock(User).find('42') { jane }
18
+ ~~~
19
+
20
+ ## Double injections (aka partial mocking)
21
+
22
+ RR utilizes a technique known as "double injection".
23
+
24
+ ~~~ ruby
25
+ my_object = MyClass.new
26
+ mock(my_object).hello
27
+ ~~~
28
+
29
+ Compare this with doing a mock in Mocha:
30
+
31
+ ~~~ ruby
32
+ my_mocked_object = mock()
33
+ my_mocked_object.expects(:hello)
34
+ ~~~
35
+
36
+ ## Pure mock objects
37
+
38
+ If you wish to use objects for the sole purpose of being a mock, you can do so
39
+ by creating an empty object:
40
+
41
+ ~~~ ruby
42
+ mock(my_mock_object = Object.new).hello
43
+ ~~~
44
+
45
+ However as a shortcut you can also use #mock!:
46
+
47
+ ~~~ ruby
48
+ # Create a new mock object with an empty #hello method, then retrieve that mock
49
+ # object via the #subject method
50
+ my_mock_object = mock!.hello.subject
51
+ ~~~
52
+
53
+ ## No #should_receive or #expects method
54
+
55
+ RR uses #method_missing to set your method expectation. This means you do not
56
+ need to use a method such as #should_receive or #expects.
57
+
58
+ ~~~ ruby
59
+ # In Mocha, #expects sets the #hello method expectation:
60
+ my_object.expects(:hello)
61
+ # Using rspec-mocks, #should_receive sets the #hello method expectation:
62
+ my_object.should_receive(:hello)
63
+ # And here's how you say it using RR:
64
+ mock(my_object).hello
65
+ ~~~
66
+
67
+ ## #with method call is not necessary
68
+
69
+ The fact that RR uses #method_missing also makes using the #with method
70
+ unnecessary in most circumstances to set the argument expectation itself
71
+ (although you can still use it if you want):
72
+
73
+ ~~~ ruby
74
+ # Mocha
75
+ my_object.expects(:hello).with('bob', 'jane')
76
+ # rspec-mocks
77
+ my_object.should_receive(:hello).with('bob', 'jane')
78
+ # RR
79
+ mock(my_object).hello('bob', 'jane')
80
+ mock(my_object).hello.with('bob', 'jane') # same thing, just more verbose
81
+ ~~~
82
+
83
+ ## Using a block to set the return value
84
+
85
+ RR supports using a block to set the return value as opposed to a specific
86
+ method call (although again, you can use #returns if you like):
87
+
88
+ ~~~ ruby
89
+ # Mocha
90
+ my_object.expects(:hello).with('bob', 'jane').returns('Hello Bob and Jane')
91
+ # rspec-mocks
92
+ my_object.should_receive(:hello).with('bob', 'jane') { 'Hello Bob and Jane' }
93
+ my_object.should_receive(:hello).with('bob', 'jane').and_return('Hello Bob and Jane') # same thing, just more verbose
94
+ # RR
95
+ mock(my_object).hello('bob', 'jane') { 'Hello Bob and Jane' }
96
+ mock(my_object).hello('bob', 'jane').returns('Hello Bob and Jane') # same thing, just more verbose
@@ -0,0 +1,616 @@
1
+ # API overview
2
+
3
+ To create a double on an object, you can use the following methods:
4
+
5
+ * #mock / #mock!
6
+ * #stub / #stub!
7
+ * #dont_allow / #dont_allow!
8
+ * #proxy / #proxy!
9
+ * #instance_of / #instance_of!
10
+
11
+ These methods are composable. #mock, #stub, and #dont_allow can be used by
12
+ themselves and are mutually exclusive. #proxy and #instance_of must be chained
13
+ with #mock or #stub. You can also chain #proxy and #instance_of together.
14
+
15
+ The ! (bang) version of these methods causes the subject object of the Double to
16
+ be instantiated.
17
+
18
+ ## #mock
19
+
20
+ \#mock replaces the method on the object with an expectation and implementation.
21
+ The expectations are a mock will be called with certain arguments a certain
22
+ number of times (the default is once). You can also set the return value of the
23
+ method invocation.
24
+
25
+ *Learn more: <http://xunitpatterns.com/Mock%20Object.html>*
26
+
27
+ The following example sets an expectation that the view will receive a method
28
+ call to #render with the arguments `{:partial => "user_info"}` once. When the
29
+ method is called, `"Information"` is returned.
30
+
31
+ ~~~ ruby
32
+ view = controller.template
33
+ mock(view).render(:partial => "user_info") {"Information"}
34
+ ~~~
35
+
36
+ You can also allow any number of arguments to be passed into the mock like
37
+ this:
38
+
39
+ ~~~ ruby
40
+ mock(view).render.with_any_args.twice do |*args|
41
+ if args.first == {:partial => "user_info"}
42
+ "User Info"
43
+ else
44
+ "Stuff in the view #{args.inspect}"
45
+ end
46
+ end
47
+ ~~~
48
+
49
+ ## #stub
50
+
51
+ \#stub replaces the method on the object with only an implementation. You can
52
+ still use arguments to differentiate which stub gets invoked.
53
+
54
+ *Learn more: <http://xunitpatterns.com/Test%20Stub.html>*
55
+
56
+ The following example makes the User.find method return `jane` when passed "42"
57
+ and returns `bob` when passed "99". If another id is passed to User.find, an
58
+ exception is raised.
59
+
60
+ ~~~ ruby
61
+ jane = User.new
62
+ bob = User.new
63
+ stub(User).find('42') {jane}
64
+ stub(User).find('99') {bob}
65
+ stub(User).find do |id|
66
+ raise "Unexpected id #{id.inspect} passed to me"
67
+ end
68
+ ~~~
69
+
70
+ ## #dont_allow (aliased to #do_not_allow, #dont_call, and #do_not_call)
71
+
72
+ \#dont_allow is the opposite of #mock -- it sets an expectation on the Double
73
+ that it will never be called. If the Double actually does end up being called, a
74
+ TimesCalledError is raised.
75
+
76
+ ~~~ ruby
77
+ dont_allow(User).find('42')
78
+ User.find('42') # raises a TimesCalledError
79
+ ~~~
80
+
81
+ ## `mock.proxy`
82
+
83
+ `mock.proxy` replaces the method on the object with an expectation,
84
+ implementation, and also invokes the actual method. `mock.proxy` also intercepts
85
+ the return value and passes it into the return value block.
86
+
87
+ The following example makes sets an expectation that `view.render({:partial =>
88
+ "right_navigation"})` gets called once and returns the actual content of the
89
+ rendered partial template. A call to `view.render({:partial => "user_info"})`
90
+ will render the "user_info" partial template and send the content into the block
91
+ and is represented by the `html` variable. An assertion is done on the value of
92
+ `html` and `"Different html"` is returned.
93
+
94
+ ~~~ ruby
95
+ view = controller.template
96
+ mock.proxy(view).render(:partial => "right_navigation")
97
+ mock.proxy(view).render(:partial => "user_info") do |html|
98
+ html.should include("John Doe")
99
+ "Different html"
100
+ end
101
+ ~~~
102
+
103
+ You can also use `mock.proxy` to set expectations on the returned value. In the
104
+ following example, a call to User.find('5') does the normal ActiveRecord
105
+ implementation and passes the actual value, represented by the variable `bob`,
106
+ into the block. `bob` is then set with a `mock.proxy` for projects to return only
107
+ the first 3 projects. `bob` is also mocked so that #valid? returns false.
108
+
109
+ ~~~ ruby
110
+ mock.proxy(User).find('5') do |bob|
111
+ mock.proxy(bob).projects do |projects|
112
+ projects[0..3]
113
+ end
114
+ mock(bob).valid? { false }
115
+ bob
116
+ end
117
+ ~~~
118
+
119
+ ## `stub.proxy`
120
+
121
+ Intercept the return value of a method call. The following example verifies
122
+ `render(:partial)` will be called and renders the partial.
123
+
124
+ ~~~ ruby
125
+ view = controller.template
126
+ stub.proxy(view).render(:partial => "user_info") do |html|
127
+ html.should include("Joe Smith")
128
+ html
129
+ end
130
+ ~~~
131
+
132
+ ## #any_instance_of
133
+
134
+ Allows stubs to be added to all instances of a class. It works by binding to
135
+ methods from the class itself, rather than the eigenclass. This allows all
136
+ instances (excluding instances with the method redefined in the eigenclass) to
137
+ get the change.
138
+
139
+ Due to Ruby runtime limitations, mocks will not work as expected. It's not
140
+ obviously feasible (without an ObjectSpace lookup) to support all of RR's
141
+ methods (such as mocking). ObjectSpace is not readily supported in JRuby, since
142
+ it causes general slowness in the interpreter. I'm of the opinion that test
143
+ speed is more important than having mocks on all instances of a class. If there
144
+ is another solution, I'd be willing to add it.
145
+
146
+ ~~~ ruby
147
+ any_instance_of(User) do |u|
148
+ stub(u).valid? { false }
149
+ end
150
+ or
151
+ any_instance_of(User, :valid? => false)
152
+ or
153
+ any_instance_of(User, :valid? => lambda { false })
154
+ ~~~
155
+
156
+ ## Spies
157
+
158
+ Adding a DoubleInjection to an object + method (done by #stub, #mock, or
159
+ \#dont_allow) causes RR to record any method invocations to the object + method.
160
+ Assertions can then be made on the recorded method calls.
161
+
162
+ ### Test::Unit
163
+
164
+ ~~~ ruby
165
+ subject = Object.new
166
+ stub(subject).foo
167
+ subject.foo(1)
168
+ assert_received(subject) {|subject| subject.foo(1) }
169
+ assert_received(subject) {|subject| subject.bar } # This fails
170
+ ~~~
171
+
172
+ ### RSpec
173
+
174
+ ~~~ ruby
175
+ subject = Object.new
176
+ stub(subject).foo
177
+ subject.foo(1)
178
+ subject.should have_received.foo(1)
179
+ subject.should have_received.bar # This fails
180
+ ~~~
181
+
182
+ ## Block syntax
183
+
184
+ The block syntax has two modes:
185
+
186
+ * A normal block mode with a DoubleDefinitionCreatorProxy argument:
187
+
188
+ ~~~ ruby
189
+ script = MyScript.new
190
+ mock(script) do |expect|
191
+ expect.system("cd #{RAILS_ENV}") {true}
192
+ expect.system("rake foo:bar") {true}
193
+ expect.system("rake baz") {true}
194
+ end
195
+ ~~~
196
+
197
+ * An instance_eval mode where the DoubleDefinitionCreatorProxy is
198
+ instance_eval'ed:
199
+
200
+ ~~~ ruby
201
+ script = MyScript.new
202
+ mock(script) do
203
+ system("cd #{RAILS_ENV}") {true}
204
+ system("rake foo:bar") {true}
205
+ system("rake baz") {true}
206
+ end
207
+ ~~~
208
+
209
+ ## Double graphs
210
+
211
+ RR has a method-chaining API support for double graphs. For example, let's say
212
+ you want an object to receive a method call to #foo, and have the return value
213
+ receive a method call to #bar.
214
+
215
+ In RR, you would do:
216
+
217
+ ~~~ ruby
218
+ stub(object).foo.stub!.bar { :baz }
219
+ object.foo.bar #=> :baz
220
+ or:
221
+ stub(object).foo { stub!.bar {:baz} }
222
+ object.foo.bar #=> :baz
223
+ or:
224
+ bar = stub!.bar { :baz }
225
+ stub(object).foo { bar }
226
+ object.foo.bar #=> :baz
227
+ ~~~
228
+
229
+ ## Modifying doubles
230
+
231
+ Whenever you create a double by calling a method on an object you've wrapped,
232
+ you get back a special object: a DoubleDefinition. In other words:
233
+
234
+ ~~~ ruby
235
+ stub(object).foo #=> RR::DoubleDefinitions::DoubleDefinition
236
+ ~~~
237
+
238
+ There are several ways you can modify the behavior of these doubles via the
239
+ DoubleDefinition API, and they are listed in this section.
240
+
241
+ Quick note: all of these methods accept blocks as a shortcut for setting the
242
+ return value at the same time. In other words, if you have something like this:
243
+
244
+ ~~~ ruby
245
+ mock(object).foo { 'bar' }
246
+ ~~~
247
+
248
+ you can modify the mock and keep the return value like so:
249
+
250
+ ~~~ ruby
251
+ mock(object).foo.times(2) { 'bar' }
252
+ ~~~
253
+
254
+ You can even flip around the block:
255
+
256
+ ~~~ ruby
257
+ mock(object).foo { 'bar' }.times(2)
258
+ ~~~
259
+
260
+ And as we explain below, this is just a shortcut for:
261
+
262
+ ~~~ ruby
263
+ mock(object).foo.returns { 'bar' }.times(2)
264
+ ~~~
265
+
266
+ ### Stubbing method implementation / return value
267
+
268
+ There are two ways here. We have already covered this usage:
269
+
270
+ ~~~ ruby
271
+ stub(object).foo { 'bar' }
272
+ ~~~
273
+
274
+ However, you can also use #returns if it's more clear to you:
275
+
276
+ ~~~ ruby
277
+ stub(object).foo.returns { 'bar' }
278
+ ~~~
279
+
280
+ Regardless, keep in mind that you're actually supplying the implementation of
281
+ the method in question here, so you can put whatever you want in this block:
282
+
283
+ ~~~ ruby
284
+ stub(object).foo { |age, count|
285
+ raise 'hell' if age < 16
286
+ ret = yield count
287
+ blue? ? ret : 'whatever'
288
+ }
289
+ ~~~
290
+
291
+ This works for mocks as well as stubs.
292
+
293
+ ### Stubbing method implementation based on argument expectation
294
+
295
+ A double's implementation is always tied to its argument expectation. This means
296
+ that it is possible to return one value if the method is called one way and
297
+ return a second value if the method is called a second way. For example:
298
+
299
+ ~~~ ruby
300
+ stub(object).foo { 'bar' }
301
+ stub(object).foo(1, 2) { 'baz' }
302
+ object.foo #=> 'bar'
303
+ object.foo(1, 2) #=> 'baz'
304
+ ~~~
305
+
306
+ This works for mocks as well as stubs.
307
+
308
+ ### Stubbing method to yield given block
309
+
310
+ If you need to stub a method such that a block given to it is guaranteed to be
311
+ called when the method is called, then use #yields.
312
+
313
+ ~~~ ruby
314
+ This outputs: [1, 2, 3]
315
+ stub(object).foo.yields(1, 2, 3)
316
+ object.foo {|*args| pp args }
317
+ ~~~
318
+
319
+ This works for mocks as well as stubs.
320
+
321
+ ### Expecting method to be called with exact argument list
322
+
323
+ There are two ways to do this. Here is the way we have shown before:
324
+
325
+ ~~~ ruby
326
+ mock(object).foo(1, 2)
327
+ object.foo(1, 2) # ok
328
+ object.foo(3) # fails
329
+ ~~~
330
+
331
+ But if this is not clear enough to you, you can use #with:
332
+
333
+ ~~~ ruby
334
+ mock(object).foo.with(1, 2)
335
+ object.foo(1, 2) # ok
336
+ object.foo(3) # fails
337
+ ~~~
338
+
339
+ As seen above, if you create an the expectation for a set of arguments and the
340
+ method is called with another set of arguments, even if *those* arguments are of
341
+ a completely different size, you will need to create another expectation for
342
+ them somehow. A simple way to do this is to #stub the method beforehand:
343
+
344
+ ~~~ ruby
345
+ stub(object).foo
346
+ mock(object).foo(1, 2)
347
+ object.foo(1, 2) # ok
348
+ object.foo(3) # ok too
349
+ ~~~
350
+
351
+ ### Expecting method to be called with any arguments
352
+
353
+ Use #with_any_args:
354
+
355
+ ~~~ ruby
356
+ mock(object).foo.with_any_args
357
+ object.foo # ok
358
+ object.foo(1) # also ok
359
+ object.foo(1, 2) # also ok
360
+ # ... you get the idea
361
+ ~~~
362
+
363
+ ### Expecting method to be called with no arguments
364
+
365
+ Use #with_no_args:
366
+
367
+ ~~~ ruby
368
+ mock(object).foo.with_no_args
369
+ object.foo # ok
370
+ object.foo(1) # fails
371
+ ~~~
372
+
373
+ ### Expecting method to never be called
374
+
375
+ Use #never:
376
+
377
+ ~~~ ruby
378
+ mock(object).foo.never
379
+ object.foo # fails
380
+ ~~~
381
+
382
+ You can also narrow the negative expectation to a specific set of arguments.
383
+ Of course, you will still need to set explicit expectations for any other ways
384
+ that your method could be called. For instance:
385
+
386
+ ~~~ ruby
387
+ mock(object).foo.with(1, 2).never
388
+ object.foo(3, 4) # fails
389
+ ~~~
390
+
391
+ RR will complain here that this is an unexpected invocation, so we need to add
392
+ an expectation for this beforehand. We can do this easily with #stub:
393
+
394
+ ~~~ ruby
395
+ stub(object).foo
396
+ ~~~
397
+
398
+ So, a full example would look like:
399
+
400
+ ~~~ ruby
401
+ stub(object).foo
402
+ mock(object).foo.with(1, 2).never
403
+ object.foo(3, 4) # ok
404
+ object.foo(1, 2) # fails
405
+ ~~~
406
+
407
+ Alternatively, you can also use #dont_allow, although the same rules apply as
408
+ above:
409
+
410
+ ~~~ ruby
411
+ stub(object).foo
412
+ dont_allow(object).foo.with(1, 2)
413
+ object.foo(3, 4) # ok
414
+ object.foo(1, 2) # fails
415
+ ~~~
416
+
417
+ ### Expecting method to be called only once
418
+
419
+ Use #once:
420
+
421
+ ~~~ ruby
422
+ mock(object).foo.once
423
+ object.foo
424
+ object.foo # fails
425
+ ~~~
426
+
427
+ ### Expecting method to called exact number of times
428
+
429
+ Use #times:
430
+
431
+ ~~~ ruby
432
+ mock(object).foo.times(3)
433
+ object.foo
434
+ object.foo
435
+ object.foo
436
+ object.foo # fails
437
+ ~~~
438
+
439
+ ### Expecting method to be called minimum number of times
440
+
441
+ Use #at_least.
442
+
443
+ For instance, this would pass:
444
+
445
+ ~~~ ruby
446
+ mock(object).foo.at_least(3)
447
+ object.foo
448
+ object.foo
449
+ object.foo
450
+ object.foo
451
+ ~~~
452
+
453
+ But this would fail:
454
+
455
+ ~~~ ruby
456
+ mock(object).foo.at_least(3)
457
+ object.foo
458
+ object.foo
459
+ ~~~
460
+
461
+ ### Expecting method to be called maximum number of times
462
+
463
+ Use #at_most.
464
+
465
+ For instance, this would pass:
466
+
467
+ ~~~ ruby
468
+ mock(object).foo.at_most(3)
469
+ object.foo
470
+ object.foo
471
+ ~~~
472
+
473
+ But this would fail:
474
+
475
+ ~~~ ruby
476
+ mock(object).foo.at_most(3)
477
+ object.foo
478
+ object.foo
479
+ object.foo
480
+ object.foo
481
+ ~~~
482
+
483
+ ### Expecting method to be called any number of times
484
+
485
+ Use #any_times. This effectively disables the times-called expectation.
486
+
487
+ ~~~ ruby
488
+ mock(object).foo.any_times
489
+ object.foo
490
+ object.foo
491
+ object.foo
492
+ ...
493
+ ~~~
494
+
495
+ You can also use #times + the argument invocation #any_times matcher:
496
+
497
+ ~~~ ruby
498
+ mock(object).foo.times(any_times)
499
+ object.foo
500
+ object.foo
501
+ object.foo
502
+ ...
503
+ ~~~
504
+
505
+
506
+
507
+ ## Argument wildcard matchers
508
+
509
+ RR also has several methods which you can use with argument expectations which
510
+ act as placeholders for arguments. When RR goes to verify the argument
511
+ expectation it will compare the placeholders with the actual arguments the
512
+ method was called with, and if they match then the test passes (hence
513
+ "matchers").
514
+
515
+ ### #anything
516
+
517
+ Matches any value.
518
+
519
+ ~~~ ruby
520
+ mock(object).foobar(1, anything)
521
+ object.foobar(1, :my_symbol)
522
+ ~~~
523
+
524
+ ### #is_a
525
+
526
+ Matches an object which `.is_a?(*Class*)`.
527
+
528
+ ~~~ ruby
529
+ mock(object).foobar(is_a(Time))
530
+ object.foobar(Time.now)
531
+ ~~~
532
+
533
+ ### #numeric
534
+
535
+ Matches a value which `.is_a?(Numeric)`.
536
+
537
+ ~~~ ruby
538
+ mock(object).foobar(numeric)
539
+ object.foobar(99)
540
+ ~~~~
541
+
542
+ ### #boolean
543
+
544
+ Matches true or false.
545
+
546
+ ~~~ ruby
547
+ mock(object).foobar(boolean)
548
+ object.foobar(false)
549
+ ~~~
550
+
551
+ ### #duck_type
552
+
553
+ Matches an object which responds to certain methods.
554
+
555
+ ~~~ ruby
556
+ mock(object).foobar(duck_type(:walk, :talk))
557
+ arg = Object.new
558
+ def arg.walk; 'waddle'; end
559
+ def arg.talk; 'quack'; end
560
+ object.foobar(arg)
561
+ ~~~
562
+
563
+ ### Ranges
564
+
565
+ Matches a number within a certain range.
566
+
567
+ ~~~ ruby
568
+ mock(object).foobar(1..10)
569
+ object.foobar(5)
570
+ ~~~
571
+
572
+ ### Regexps
573
+
574
+ Matches a string which matches a certain regex.
575
+
576
+ ~~~ ruby
577
+ mock(object).foobar(/on/)
578
+ object.foobar("ruby on rails")
579
+ ~~~
580
+
581
+ ### #hash_including
582
+
583
+ Matches a hash which contains a subset of keys and values.
584
+
585
+ ~~~ ruby
586
+ mock(object).foobar(hash_including(:red => "#FF0000", :blue => "#0000FF"))
587
+ object.foobar({:red => "#FF0000", :blue => "#0000FF", :green => "#00FF00"})
588
+ ~~~
589
+
590
+ ### #satisfy
591
+
592
+ Matches an argument which satisfies a custom requirement.
593
+
594
+ ~~~ ruby
595
+ mock(object).foobar(satisfy {|arg| arg.length == 2 })
596
+ object.foobar("xy")
597
+ ~~~
598
+
599
+ ### Writing your own argument matchers
600
+
601
+ Writing a custom argument wildcard matcher is not difficult. See
602
+ RR::WildcardMatchers for details.
603
+
604
+ ## Invocation amount wildcard matchers
605
+
606
+ ### #any_times
607
+
608
+ Only used with #times and matches any number.
609
+
610
+ ~~~ ruby
611
+ mock(object).foo.times(any_times) { return_value }
612
+ object.foo
613
+ object.foo
614
+ object.foo
615
+ ...
616
+ ~~~