mocha-macruby 0.9.8.20100129120100

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 (172) hide show
  1. data/COPYING +3 -0
  2. data/MIT-LICENSE +7 -0
  3. data/README +39 -0
  4. data/RELEASE +294 -0
  5. data/Rakefile +214 -0
  6. data/examples/misc.rb +43 -0
  7. data/examples/mocha.rb +25 -0
  8. data/examples/stubba.rb +64 -0
  9. data/lib/mocha.rb +3 -0
  10. data/lib/mocha/any_instance_method.rb +59 -0
  11. data/lib/mocha/api.rb +173 -0
  12. data/lib/mocha/argument_iterator.rb +21 -0
  13. data/lib/mocha/backtrace_filter.rb +17 -0
  14. data/lib/mocha/cardinality.rb +95 -0
  15. data/lib/mocha/central.rb +27 -0
  16. data/lib/mocha/change_state_side_effect.rb +19 -0
  17. data/lib/mocha/class_method.rb +117 -0
  18. data/lib/mocha/configuration.rb +79 -0
  19. data/lib/mocha/deprecation.rb +22 -0
  20. data/lib/mocha/exception_raiser.rb +17 -0
  21. data/lib/mocha/expectation.rb +476 -0
  22. data/lib/mocha/expectation_error.rb +15 -0
  23. data/lib/mocha/expectation_list.rb +50 -0
  24. data/lib/mocha/in_state_ordering_constraint.rb +19 -0
  25. data/lib/mocha/inspect.rb +67 -0
  26. data/lib/mocha/instance_method.rb +16 -0
  27. data/lib/mocha/integration.rb +38 -0
  28. data/lib/mocha/integration/mini_test.rb +21 -0
  29. data/lib/mocha/integration/mini_test/assertion_counter.rb +23 -0
  30. data/lib/mocha/integration/mini_test/version_131_and_above.rb +50 -0
  31. data/lib/mocha/integration/test_unit.rb +40 -0
  32. data/lib/mocha/integration/test_unit/assertion_counter.rb +23 -0
  33. data/lib/mocha/integration/test_unit/gem_version_200.rb +49 -0
  34. data/lib/mocha/integration/test_unit/gem_version_201_and_above.rb +49 -0
  35. data/lib/mocha/integration/test_unit/ruby_version_185_and_below.rb +48 -0
  36. data/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb +50 -0
  37. data/lib/mocha/is_a.rb +9 -0
  38. data/lib/mocha/logger.rb +15 -0
  39. data/lib/mocha/metaclass.rb +13 -0
  40. data/lib/mocha/method_matcher.rb +21 -0
  41. data/lib/mocha/mock.rb +200 -0
  42. data/lib/mocha/mockery.rb +181 -0
  43. data/lib/mocha/module_method.rb +16 -0
  44. data/lib/mocha/multiple_yields.rb +20 -0
  45. data/lib/mocha/names.rb +53 -0
  46. data/lib/mocha/no_yields.rb +11 -0
  47. data/lib/mocha/object.rb +187 -0
  48. data/lib/mocha/parameter_matchers.rb +27 -0
  49. data/lib/mocha/parameter_matchers/all_of.rb +42 -0
  50. data/lib/mocha/parameter_matchers/any_of.rb +47 -0
  51. data/lib/mocha/parameter_matchers/any_parameters.rb +40 -0
  52. data/lib/mocha/parameter_matchers/anything.rb +33 -0
  53. data/lib/mocha/parameter_matchers/base.rb +15 -0
  54. data/lib/mocha/parameter_matchers/equals.rb +42 -0
  55. data/lib/mocha/parameter_matchers/has_entries.rb +45 -0
  56. data/lib/mocha/parameter_matchers/has_entry.rb +57 -0
  57. data/lib/mocha/parameter_matchers/has_key.rb +43 -0
  58. data/lib/mocha/parameter_matchers/has_value.rb +43 -0
  59. data/lib/mocha/parameter_matchers/includes.rb +41 -0
  60. data/lib/mocha/parameter_matchers/instance_of.rb +42 -0
  61. data/lib/mocha/parameter_matchers/is_a.rb +42 -0
  62. data/lib/mocha/parameter_matchers/kind_of.rb +42 -0
  63. data/lib/mocha/parameter_matchers/not.rb +42 -0
  64. data/lib/mocha/parameter_matchers/object.rb +15 -0
  65. data/lib/mocha/parameter_matchers/optionally.rb +55 -0
  66. data/lib/mocha/parameter_matchers/regexp_matches.rb +44 -0
  67. data/lib/mocha/parameter_matchers/responds_with.rb +43 -0
  68. data/lib/mocha/parameter_matchers/yaml_equivalent.rb +43 -0
  69. data/lib/mocha/parameters_matcher.rb +37 -0
  70. data/lib/mocha/pretty_parameters.rb +28 -0
  71. data/lib/mocha/return_values.rb +31 -0
  72. data/lib/mocha/sequence.rb +42 -0
  73. data/lib/mocha/single_return_value.rb +17 -0
  74. data/lib/mocha/single_yield.rb +18 -0
  75. data/lib/mocha/standalone.rb +1 -0
  76. data/lib/mocha/state_machine.rb +91 -0
  77. data/lib/mocha/stubbing_error.rb +16 -0
  78. data/lib/mocha/unexpected_invocation.rb +18 -0
  79. data/lib/mocha/yield_parameters.rb +31 -0
  80. data/lib/mocha_standalone.rb +2 -0
  81. data/lib/stubba.rb +4 -0
  82. data/test/acceptance/acceptance_test_helper.rb +38 -0
  83. data/test/acceptance/api_test.rb +139 -0
  84. data/test/acceptance/bug_18914_test.rb +43 -0
  85. data/test/acceptance/bug_21465_test.rb +34 -0
  86. data/test/acceptance/bug_21563_test.rb +25 -0
  87. data/test/acceptance/expected_invocation_count_test.rb +196 -0
  88. data/test/acceptance/failure_messages_test.rb +64 -0
  89. data/test/acceptance/minitest_test.rb +153 -0
  90. data/test/acceptance/mocha_example_test.rb +98 -0
  91. data/test/acceptance/mocha_test_result_test.rb +84 -0
  92. data/test/acceptance/mock_test.rb +100 -0
  93. data/test/acceptance/mock_with_initializer_block_test.rb +51 -0
  94. data/test/acceptance/mocked_methods_dispatch_test.rb +78 -0
  95. data/test/acceptance/optional_parameters_test.rb +70 -0
  96. data/test/acceptance/parameter_matcher_test.rb +209 -0
  97. data/test/acceptance/partial_mocks_test.rb +47 -0
  98. data/test/acceptance/return_value_test.rb +52 -0
  99. data/test/acceptance/sequence_test.rb +186 -0
  100. data/test/acceptance/states_test.rb +70 -0
  101. data/test/acceptance/stub_any_instance_method_test.rb +195 -0
  102. data/test/acceptance/stub_class_method_test.rb +203 -0
  103. data/test/acceptance/stub_everything_test.rb +56 -0
  104. data/test/acceptance/stub_instance_method_test.rb +203 -0
  105. data/test/acceptance/stub_module_method_test.rb +163 -0
  106. data/test/acceptance/stub_test.rb +52 -0
  107. data/test/acceptance/stubba_example_test.rb +102 -0
  108. data/test/acceptance/stubba_test.rb +15 -0
  109. data/test/acceptance/stubba_test_result_test.rb +66 -0
  110. data/test/acceptance/stubbing_error_backtrace_test.rb +64 -0
  111. data/test/acceptance/stubbing_method_unnecessarily_test.rb +65 -0
  112. data/test/acceptance/stubbing_non_existent_any_instance_method_test.rb +130 -0
  113. data/test/acceptance/stubbing_non_existent_class_method_test.rb +157 -0
  114. data/test/acceptance/stubbing_non_existent_instance_method_test.rb +147 -0
  115. data/test/acceptance/stubbing_non_public_any_instance_method_test.rb +130 -0
  116. data/test/acceptance/stubbing_non_public_class_method_test.rb +163 -0
  117. data/test/acceptance/stubbing_non_public_instance_method_test.rb +143 -0
  118. data/test/acceptance/stubbing_on_non_mock_object_test.rb +64 -0
  119. data/test/deprecation_disabler.rb +15 -0
  120. data/test/execution_point.rb +36 -0
  121. data/test/method_definer.rb +24 -0
  122. data/test/simple_counter.rb +13 -0
  123. data/test/test_helper.rb +25 -0
  124. data/test/test_runner.rb +33 -0
  125. data/test/unit/any_instance_method_test.rb +126 -0
  126. data/test/unit/array_inspect_test.rb +16 -0
  127. data/test/unit/backtrace_filter_test.rb +19 -0
  128. data/test/unit/cardinality_test.rb +56 -0
  129. data/test/unit/central_test.rb +65 -0
  130. data/test/unit/change_state_side_effect_test.rb +41 -0
  131. data/test/unit/class_method_test.rb +295 -0
  132. data/test/unit/configuration_test.rb +38 -0
  133. data/test/unit/date_time_inspect_test.rb +21 -0
  134. data/test/unit/exception_raiser_test.rb +42 -0
  135. data/test/unit/expectation_list_test.rb +57 -0
  136. data/test/unit/expectation_test.rb +480 -0
  137. data/test/unit/hash_inspect_test.rb +16 -0
  138. data/test/unit/in_state_ordering_constraint_test.rb +43 -0
  139. data/test/unit/metaclass_test.rb +22 -0
  140. data/test/unit/method_matcher_test.rb +23 -0
  141. data/test/unit/mock_test.rb +302 -0
  142. data/test/unit/mockery_test.rb +149 -0
  143. data/test/unit/multiple_yields_test.rb +18 -0
  144. data/test/unit/no_yields_test.rb +18 -0
  145. data/test/unit/object_inspect_test.rb +37 -0
  146. data/test/unit/object_test.rb +82 -0
  147. data/test/unit/parameter_matchers/all_of_test.rb +26 -0
  148. data/test/unit/parameter_matchers/any_of_test.rb +26 -0
  149. data/test/unit/parameter_matchers/anything_test.rb +21 -0
  150. data/test/unit/parameter_matchers/equals_test.rb +25 -0
  151. data/test/unit/parameter_matchers/has_entries_test.rb +51 -0
  152. data/test/unit/parameter_matchers/has_entry_test.rb +82 -0
  153. data/test/unit/parameter_matchers/has_key_test.rb +55 -0
  154. data/test/unit/parameter_matchers/has_value_test.rb +57 -0
  155. data/test/unit/parameter_matchers/includes_test.rb +44 -0
  156. data/test/unit/parameter_matchers/instance_of_test.rb +25 -0
  157. data/test/unit/parameter_matchers/is_a_test.rb +25 -0
  158. data/test/unit/parameter_matchers/kind_of_test.rb +25 -0
  159. data/test/unit/parameter_matchers/not_test.rb +26 -0
  160. data/test/unit/parameter_matchers/regexp_matches_test.rb +46 -0
  161. data/test/unit/parameter_matchers/responds_with_test.rb +25 -0
  162. data/test/unit/parameter_matchers/stub_matcher.rb +27 -0
  163. data/test/unit/parameter_matchers/yaml_equivalent_test.rb +25 -0
  164. data/test/unit/parameters_matcher_test.rb +121 -0
  165. data/test/unit/return_values_test.rb +63 -0
  166. data/test/unit/sequence_test.rb +104 -0
  167. data/test/unit/single_return_value_test.rb +14 -0
  168. data/test/unit/single_yield_test.rb +18 -0
  169. data/test/unit/state_machine_test.rb +98 -0
  170. data/test/unit/string_inspect_test.rb +11 -0
  171. data/test/unit/yield_parameters_test.rb +93 -0
  172. metadata +240 -0
data/examples/misc.rb ADDED
@@ -0,0 +1,43 @@
1
+ require 'test/unit'
2
+ require 'mocha'
3
+
4
+ class MiscExampleTest < Test::Unit::TestCase
5
+
6
+ def test_mocking_a_class_method
7
+ product = Product.new
8
+ Product.expects(:find).with(1).returns(product)
9
+ assert_equal product, Product.find(1)
10
+ end
11
+
12
+ def test_mocking_an_instance_method_on_a_real_object
13
+ product = Product.new
14
+ product.expects(:save).returns(true)
15
+ assert product.save
16
+ end
17
+
18
+ def test_stubbing_instance_methods_on_real_objects
19
+ prices = [stub(:pence => 1000), stub(:pence => 2000)]
20
+ product = Product.new
21
+ product.stubs(:prices).returns(prices)
22
+ assert_equal [1000, 2000], product.prices.collect {|p| p.pence}
23
+ end
24
+
25
+ def test_stubbing_an_instance_method_on_all_instances_of_a_class
26
+ Product.any_instance.stubs(:name).returns('stubbed_name')
27
+ product = Product.new
28
+ assert_equal 'stubbed_name', product.name
29
+ end
30
+
31
+ def test_traditional_mocking
32
+ object = mock()
33
+ object.expects(:expected_method).with(:p1, :p2).returns(:result)
34
+ assert_equal :result, object.expected_method(:p1, :p2)
35
+ end
36
+
37
+ def test_shortcuts
38
+ object = stub(:method1 => :result1, :method2 => :result2)
39
+ assert_equal :result1, object.method1
40
+ assert_equal :result2, object.method2
41
+ end
42
+
43
+ end
data/examples/mocha.rb ADDED
@@ -0,0 +1,25 @@
1
+ class Enterprise
2
+
3
+ def initialize(dilithium)
4
+ @dilithium = dilithium
5
+ end
6
+
7
+ def go(warp_factor)
8
+ warp_factor.times { @dilithium.nuke(:anti_matter) }
9
+ end
10
+
11
+ end
12
+
13
+ require 'test/unit'
14
+ require 'mocha'
15
+
16
+ class EnterpriseTest < Test::Unit::TestCase
17
+
18
+ def test_should_boldly_go
19
+ dilithium = mock()
20
+ dilithium.expects(:nuke).with(:anti_matter).at_least_once # auto-verified at end of test
21
+ enterprise = Enterprise.new(dilithium)
22
+ enterprise.go(2)
23
+ end
24
+
25
+ end
@@ -0,0 +1,64 @@
1
+ class Order
2
+
3
+ attr_accessor :shipped_on
4
+
5
+ def total_cost
6
+ line_items.inject(0) { |total, line_item| total + line_item.price } + shipping_cost
7
+ end
8
+
9
+ def total_weight
10
+ line_items.inject(0) { |total, line_item| total + line_item.weight }
11
+ end
12
+
13
+ def shipping_cost
14
+ total_weight * 5 + 10
15
+ end
16
+
17
+ class << self
18
+
19
+ def find_all
20
+ # Database.connection.execute('select * from orders...
21
+ end
22
+
23
+ def number_shipped_since(date)
24
+ find_all.select { |order| order.shipped_on > date }.length
25
+ end
26
+
27
+ def unshipped_value
28
+ find_all.inject(0) { |total, order| order.shipped_on ? total : total + order.total_cost }
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ require 'test/unit'
36
+ require 'mocha'
37
+
38
+ class OrderTest < Test::Unit::TestCase
39
+
40
+ # illustrates stubbing instance method
41
+ def test_should_calculate_shipping_cost_based_on_total_weight
42
+ order = Order.new
43
+ order.stubs(:total_weight).returns(10)
44
+ assert_equal 60, order.shipping_cost
45
+ end
46
+
47
+ # illustrates stubbing class method
48
+ def test_should_count_number_of_orders_shipped_after_specified_date
49
+ now = Time.now; week_in_secs = 7 * 24 * 60 * 60
50
+ order_1 = Order.new; order_1.shipped_on = now - 1 * week_in_secs
51
+ order_2 = Order.new; order_2.shipped_on = now - 3 * week_in_secs
52
+ Order.stubs(:find_all).returns([order_1, order_2])
53
+ assert_equal 1, Order.number_shipped_since(now - 2 * week_in_secs)
54
+ end
55
+
56
+ # illustrates stubbing instance method for all instances of a class
57
+ def test_should_calculate_value_of_unshipped_orders
58
+ Order.stubs(:find_all).returns([Order.new, Order.new, Order.new])
59
+ Order.any_instance.stubs(:shipped_on).returns(nil)
60
+ Order.any_instance.stubs(:total_cost).returns(10)
61
+ assert_equal 30, Order.unshipped_value
62
+ end
63
+
64
+ end
data/lib/mocha.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'mocha_standalone'
2
+ require 'mocha/configuration'
3
+ require 'mocha/integration'
@@ -0,0 +1,59 @@
1
+ require 'mocha/class_method'
2
+
3
+ module Mocha
4
+
5
+ class AnyInstanceMethod < ClassMethod
6
+
7
+ def unstub
8
+ remove_new_method
9
+ restore_original_method
10
+ stubbee.any_instance.reset_mocha
11
+ end
12
+
13
+ def mock
14
+ stubbee.any_instance.mocha
15
+ end
16
+
17
+ def hide_original_method
18
+ if method_exists?(method)
19
+ begin
20
+ stubbee.send(:alias_method, hidden_method, method)
21
+ rescue NameError
22
+ # deal with nasties like ActiveRecord::Associations::AssociationProxy
23
+ end
24
+ end
25
+ end
26
+
27
+ def define_new_method
28
+ stubbee.class_eval(%{
29
+ def #{method}(*args, &block)
30
+ self.class.any_instance.mocha.method_missing(:#{method}, *args, &block)
31
+ end
32
+ }, __FILE__, __LINE__)
33
+ end
34
+
35
+ def remove_new_method
36
+ stubbee.send(:remove_method, method)
37
+ end
38
+
39
+ def restore_original_method
40
+ if method_exists?(hidden_method)
41
+ begin
42
+ stubbee.send(:alias_method, method, hidden_method)
43
+ stubbee.send(:remove_method, hidden_method)
44
+ rescue NameError
45
+ # deal with nasties like ActiveRecord::Associations::AssociationProxy
46
+ end
47
+ end
48
+ end
49
+
50
+ def method_exists?(method)
51
+ return true if stubbee.public_instance_methods(false).include?(method)
52
+ return true if stubbee.protected_instance_methods(false).include?(method)
53
+ return true if stubbee.private_instance_methods(false).include?(method)
54
+ return false
55
+ end
56
+
57
+ end
58
+
59
+ end
data/lib/mocha/api.rb ADDED
@@ -0,0 +1,173 @@
1
+ require 'mocha/parameter_matchers'
2
+ require 'mocha/mockery'
3
+ require 'mocha/sequence'
4
+
5
+ module Mocha # :nodoc:
6
+
7
+ # Methods added to Test::Unit::TestCase or equivalent.
8
+ module API
9
+
10
+ include ParameterMatchers
11
+
12
+ # :call-seq: mock(name, &block) -> mock object
13
+ # mock(expected_methods = {}, &block) -> mock object
14
+ # mock(name, expected_methods = {}, &block) -> mock object
15
+ #
16
+ # Creates a mock object.
17
+ #
18
+ # +name+ is a +String+ identifier for the mock object.
19
+ #
20
+ # +expected_methods+ is a +Hash+ with expected method name symbols as keys and corresponding return values as values.
21
+ #
22
+ # Note that (contrary to expectations set up by #stub) these expectations <b>must</b> be fulfilled during the test.
23
+ # def test_product
24
+ # product = mock('ipod_product', :manufacturer => 'ipod', :price => 100)
25
+ # assert_equal 'ipod', product.manufacturer
26
+ # assert_equal 100, product.price
27
+ # # an error will be raised unless both Product#manufacturer and Product#price have been called
28
+ # end
29
+ #
30
+ # +block+ is an optional block to be evaluated against the mock object instance, giving an alernative way to set up expectations & stubs.
31
+ # def test_product
32
+ # product = mock('ipod_product') do
33
+ # expects(:manufacturer).returns('ipod')
34
+ # expects(:price).returns(100)
35
+ # end
36
+ # assert_equal 'ipod', product.manufacturer
37
+ # assert_equal 100, product.price
38
+ # # an error will be raised unless both Product#manufacturer and Product#price have been called
39
+ # end
40
+ def mock(*arguments, &block)
41
+ name = arguments.shift if arguments.first.is_a?(String)
42
+ expectations = arguments.shift || {}
43
+ mock = name ? Mockery.instance.named_mock(name, &block) : Mockery.instance.unnamed_mock(&block)
44
+ mock.expects(expectations)
45
+ mock
46
+ end
47
+
48
+ # :call-seq: stub(name, &block) -> mock object
49
+ # stub(stubbed_methods = {}, &block) -> mock object
50
+ # stub(name, stubbed_methods = {}, &block) -> mock object
51
+ #
52
+ # Creates a mock object.
53
+ #
54
+ # +name+ is a +String+ identifier for the mock object.
55
+ #
56
+ # +stubbed_methods+ is a +Hash+ with stubbed method name symbols as keys and corresponding return values as values.
57
+ # Note that (contrary to expectations set up by #mock) these expectations <b>need not</b> be fulfilled during the test.
58
+ # def test_product
59
+ # product = stub('ipod_product', :manufacturer => 'ipod', :price => 100)
60
+ # assert_equal 'ipod', product.manufacturer
61
+ # assert_equal 100, product.price
62
+ # # an error will not be raised even if Product#manufacturer and Product#price have not been called
63
+ # end
64
+ #
65
+ # +block+ is an optional block to be evaluated against the mock object instance, giving an alernative way to set up expectations & stubs.
66
+ # def test_product
67
+ # product = stub('ipod_product') do
68
+ # stubs(:manufacturer).returns('ipod')
69
+ # stubs(:price).returns(100)
70
+ # end
71
+ # assert_equal 'ipod', product.manufacturer
72
+ # assert_equal 100, product.price
73
+ # # an error will not be raised even if Product#manufacturer and Product#price have not been called
74
+ # end
75
+ def stub(*arguments, &block)
76
+ name = arguments.shift if arguments.first.is_a?(String)
77
+ expectations = arguments.shift || {}
78
+ stub = name ? Mockery.instance.named_mock(name, &block) : Mockery.instance.unnamed_mock(&block)
79
+ stub.stubs(expectations)
80
+ stub
81
+ end
82
+
83
+ # :call-seq: stub_everything(name, &block) -> mock object
84
+ # stub_everything(stubbed_methods = {}, &block) -> mock object
85
+ # stub_everything(name, stubbed_methods = {}, &block) -> mock object
86
+ #
87
+ # Creates a mock object that accepts calls to any method.
88
+ #
89
+ # By default it will return +nil+ for any method call.
90
+ #
91
+ # +block+ is a block to be evaluated against the mock object instance, giving an alernative way to set up expectations & stubs.
92
+ #
93
+ # +name+ and +stubbed_methods+ work in the same way as for #stub.
94
+ # def test_product
95
+ # product = stub_everything('ipod_product', :price => 100)
96
+ # assert_nil product.manufacturer
97
+ # assert_nil product.any_old_method
98
+ # assert_equal 100, product.price
99
+ # end
100
+ def stub_everything(*arguments, &block)
101
+ name = arguments.shift if arguments.first.is_a?(String)
102
+ expectations = arguments.shift || {}
103
+ stub = name ? Mockery.instance.named_mock(name, &block) : Mockery.instance.unnamed_mock(&block)
104
+ stub.stub_everything
105
+ stub.stubs(expectations)
106
+ stub
107
+ end
108
+
109
+ # :call-seq: sequence(name) -> sequence
110
+ #
111
+ # Returns a new sequence that is used to constrain the order in which expectations can occur.
112
+ #
113
+ # Specify that an expected invocation must occur in within a named +sequence+ by using Expectation#in_sequence.
114
+ #
115
+ # See also Expectation#in_sequence.
116
+ # breakfast = sequence('breakfast')
117
+ #
118
+ # egg = mock('egg')
119
+ # egg.expects(:crack).in_sequence(breakfast)
120
+ # egg.expects(:fry).in_sequence(breakfast)
121
+ # egg.expects(:eat).in_sequence(breakfast)
122
+ def sequence(name)
123
+ Sequence.new(name)
124
+ end
125
+
126
+ # :call-seq: states(name) -> state_machine
127
+ #
128
+ # Returns a new +state_machine+ that is used to constrain the order in which expectations can occur.
129
+ #
130
+ # Specify the initial +state+ of the +state_machine+ by using StateMachine#starts_as.
131
+ #
132
+ # Specify that an expected invocation should change the +state+ of the +state_machine+ by using Expectation#then.
133
+ #
134
+ # Specify that an expected invocation should be constrained to occur within a particular +state+ by using Expectation#when.
135
+ #
136
+ # A test can contain multiple +state_machines+.
137
+ #
138
+ # See also Expectation#then, Expectation#when and StateMachine.
139
+ # power = states('power').starts_as('off')
140
+ #
141
+ # radio = mock('radio')
142
+ # radio.expects(:switch_on).then(power.is('on'))
143
+ # radio.expects(:select_channel).with('BBC Radio 4').when(power.is('on'))
144
+ # radio.expects(:adjust_volume).with(+5).when(power.is('on'))
145
+ # radio.expects(:select_channel).with('BBC World Service').when(power.is('on'))
146
+ # radio.expects(:adjust_volume).with(-5).when(power.is('on'))
147
+ # radio.expects(:switch_off).then(power.is('off'))
148
+ def states(name)
149
+ Mockery.instance.new_state_machine(name)
150
+ end
151
+
152
+ def mocha_setup # :nodoc:
153
+ end
154
+
155
+ def mocha_verify(assertion_counter = nil) # :nodoc:
156
+ Mockery.instance.verify(assertion_counter)
157
+ end
158
+
159
+ def mocha_teardown # :nodoc:
160
+ Mockery.instance.teardown
161
+ Mockery.reset_instance
162
+ end
163
+
164
+ end
165
+
166
+ def self.const_missing(name)
167
+ return super unless name == :Standalone
168
+ require 'mocha/deprecation'
169
+ Deprecation.warning "Mocha::Standalone has been renamed to Mocha::API"
170
+ return API
171
+ end
172
+
173
+ end
@@ -0,0 +1,21 @@
1
+ module Mocha
2
+
3
+ class ArgumentIterator
4
+
5
+ def initialize(argument)
6
+ @argument = argument
7
+ end
8
+
9
+ def each(&block)
10
+ if @argument.is_a?(Hash) then
11
+ @argument.each do |method_name, return_value|
12
+ block.call(method_name, return_value)
13
+ end
14
+ else
15
+ block.call(@argument)
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,17 @@
1
+ module Mocha
2
+
3
+ class BacktraceFilter
4
+
5
+ LIB_DIRECTORY = File.expand_path(File.join(File.dirname(__FILE__), "..")) + File::SEPARATOR
6
+
7
+ def initialize(lib_directory = LIB_DIRECTORY)
8
+ @lib_directory = lib_directory
9
+ end
10
+
11
+ def filtered(backtrace)
12
+ backtrace.reject { |location| Regexp.new(@lib_directory).match(File.expand_path(location)) }
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,95 @@
1
+ module Mocha
2
+
3
+ class Cardinality
4
+
5
+ INFINITY = 1 / 0.0
6
+
7
+ class << self
8
+
9
+ def exactly(count)
10
+ new(count, count)
11
+ end
12
+
13
+ def at_least(count)
14
+ new(count, INFINITY)
15
+ end
16
+
17
+ def at_most(count)
18
+ new(0, count)
19
+ end
20
+
21
+ def times(range_or_count)
22
+ case range_or_count
23
+ when Range then new(range_or_count.first, range_or_count.last)
24
+ else new(range_or_count, range_or_count)
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ def initialize(required, maximum)
31
+ @required, @maximum = required, maximum
32
+ end
33
+
34
+ def invocations_allowed?(invocation_count)
35
+ invocation_count < maximum
36
+ end
37
+
38
+ def satisfied?(invocations_so_far)
39
+ invocations_so_far >= required
40
+ end
41
+
42
+ def needs_verifying?
43
+ !allowed_any_number_of_times?
44
+ end
45
+
46
+ def verified?(invocation_count)
47
+ (invocation_count >= required) && (invocation_count <= maximum)
48
+ end
49
+
50
+ def allowed_any_number_of_times?
51
+ required == 0 && infinite?(maximum)
52
+ end
53
+
54
+ def used?(invocation_count)
55
+ (invocation_count > 0) || (maximum == 0)
56
+ end
57
+
58
+ def mocha_inspect
59
+ if allowed_any_number_of_times?
60
+ "allowed any number of times"
61
+ else
62
+ if required == 0 && maximum == 0
63
+ "expected never"
64
+ elsif required == maximum
65
+ "expected exactly #{times(required)}"
66
+ elsif infinite?(maximum)
67
+ "expected at least #{times(required)}"
68
+ elsif required == 0
69
+ "expected at most #{times(maximum)}"
70
+ else
71
+ "expected between #{required} and #{times(maximum)}"
72
+ end
73
+ end
74
+ end
75
+
76
+ protected
77
+
78
+ attr_reader :required, :maximum
79
+
80
+ def times(number)
81
+ case number
82
+ when 0 then "no times"
83
+ when 1 then "once"
84
+ when 2 then "twice"
85
+ else "#{number} times"
86
+ end
87
+ end
88
+
89
+ def infinite?(number)
90
+ number.respond_to?(:infinite?) && number.infinite?
91
+ end
92
+
93
+ end
94
+
95
+ end