rr 1.1.1.rc1 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ ~~~