mocha 0.5.6 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. data/README +4 -4
  2. data/RELEASE +45 -0
  3. data/Rakefile +55 -33
  4. data/lib/mocha.rb +1 -0
  5. data/lib/mocha/any_instance_method.rb +24 -4
  6. data/lib/mocha/backtrace_filter.rb +17 -0
  7. data/lib/mocha/cardinality.rb +92 -0
  8. data/lib/mocha/central.rb +1 -9
  9. data/lib/mocha/change_state_side_effect.rb +19 -0
  10. data/lib/mocha/class_method.rb +25 -5
  11. data/lib/mocha/configuration.rb +60 -0
  12. data/lib/mocha/exception_raiser.rb +1 -1
  13. data/lib/mocha/expectation.rb +109 -48
  14. data/lib/mocha/expectation_error.rb +6 -6
  15. data/lib/mocha/expectation_list.rb +10 -14
  16. data/lib/mocha/in_state_ordering_constraint.rb +19 -0
  17. data/lib/mocha/instance_method.rb +9 -0
  18. data/lib/mocha/logger.rb +15 -0
  19. data/lib/mocha/mock.rb +19 -14
  20. data/lib/mocha/mockery.rb +166 -0
  21. data/lib/mocha/module_method.rb +17 -0
  22. data/lib/mocha/names.rb +53 -0
  23. data/lib/mocha/object.rb +26 -9
  24. data/lib/mocha/parameter_matchers.rb +2 -1
  25. data/lib/mocha/parameter_matchers/all_of.rb +3 -3
  26. data/lib/mocha/parameter_matchers/any_of.rb +3 -3
  27. data/lib/mocha/parameter_matchers/anything.rb +1 -1
  28. data/lib/mocha/parameter_matchers/has_entries.rb +4 -1
  29. data/lib/mocha/parameter_matchers/has_entry.rb +3 -2
  30. data/lib/mocha/parameter_matchers/has_key.rb +1 -1
  31. data/lib/mocha/parameter_matchers/has_value.rb +1 -1
  32. data/lib/mocha/parameter_matchers/not.rb +2 -2
  33. data/lib/mocha/parameter_matchers/object.rb +1 -1
  34. data/lib/mocha/parameter_matchers/optionally.rb +22 -0
  35. data/lib/mocha/parameter_matchers/regexp_matches.rb +2 -2
  36. data/lib/mocha/parameter_matchers/responds_with.rb +43 -0
  37. data/lib/mocha/parameter_matchers/yaml_equivalent.rb +43 -0
  38. data/lib/mocha/single_return_value.rb +2 -9
  39. data/lib/mocha/standalone.rb +151 -17
  40. data/lib/mocha/state_machine.rb +91 -0
  41. data/lib/mocha/stubbing_error.rb +16 -0
  42. data/lib/mocha/test_case_adapter.rb +76 -22
  43. data/lib/stubba.rb +2 -1
  44. data/test/acceptance/acceptance_test_helper.rb +38 -0
  45. data/test/acceptance/bug_18914_test.rb +43 -0
  46. data/test/acceptance/{expected_invocation_count_acceptance_test.rb → expected_invocation_count_test.rb} +29 -20
  47. data/test/acceptance/failure_messages_test.rb +64 -0
  48. data/test/acceptance/{mocha_acceptance_test.rb → mocha_example_test.rb} +5 -5
  49. data/test/{integration/mocha_test_result_integration_test.rb → acceptance/mocha_test_result_test.rb} +19 -40
  50. data/test/acceptance/mock_test.rb +100 -0
  51. data/test/acceptance/{mock_with_initializer_block_acceptance_test.rb → mock_with_initializer_block_test.rb} +12 -5
  52. data/test/acceptance/{mocked_methods_dispatch_acceptance_test.rb → mocked_methods_dispatch_test.rb} +12 -5
  53. data/test/acceptance/{optional_parameters_acceptance_test.rb → optional_parameters_test.rb} +11 -4
  54. data/test/acceptance/{parameter_matcher_acceptance_test.rb → parameter_matcher_test.rb} +67 -5
  55. data/test/acceptance/{partial_mocks_acceptance_test.rb → partial_mocks_test.rb} +12 -5
  56. data/test/acceptance/return_value_test.rb +52 -0
  57. data/test/acceptance/{sequence_acceptance_test.rb → sequence_test.rb} +13 -6
  58. data/test/acceptance/{standalone_acceptance_test.rb → standalone_test.rb} +19 -11
  59. data/test/acceptance/states_test.rb +70 -0
  60. data/test/acceptance/stub_any_instance_method_test.rb +195 -0
  61. data/test/acceptance/stub_class_method_test.rb +203 -0
  62. data/test/acceptance/stub_everything_test.rb +56 -0
  63. data/test/acceptance/stub_instance_method_test.rb +165 -0
  64. data/test/acceptance/stub_module_method_test.rb +163 -0
  65. data/test/acceptance/stub_test.rb +52 -0
  66. data/test/acceptance/{stubba_acceptance_test.rb → stubba_example_test.rb} +1 -1
  67. data/test/{integration/stubba_test_result_integration_test.rb → acceptance/stubba_test_result_test.rb} +17 -36
  68. data/test/acceptance/stubbing_error_backtrace_test.rb +64 -0
  69. data/test/acceptance/stubbing_method_unnecessarily_test.rb +65 -0
  70. data/test/acceptance/stubbing_non_existent_any_instance_method_test.rb +130 -0
  71. data/test/acceptance/stubbing_non_existent_class_method_test.rb +155 -0
  72. data/test/acceptance/stubbing_non_existent_instance_method_test.rb +145 -0
  73. data/test/acceptance/stubbing_non_public_any_instance_method_test.rb +130 -0
  74. data/test/acceptance/stubbing_non_public_class_method_test.rb +161 -0
  75. data/test/acceptance/stubbing_non_public_instance_method_test.rb +141 -0
  76. data/test/acceptance/stubbing_on_non_mock_object_test.rb +64 -0
  77. data/test/execution_point.rb +3 -1
  78. data/test/simple_counter.rb +13 -0
  79. data/test/test_helper.rb +0 -1
  80. data/test/test_runner.rb +6 -4
  81. data/test/unit/any_instance_method_test.rb +1 -1
  82. data/test/unit/array_inspect_test.rb +1 -1
  83. data/test/unit/backtrace_filter_test.rb +19 -0
  84. data/test/unit/cardinality_test.rb +56 -0
  85. data/test/unit/central_test.rb +4 -63
  86. data/test/unit/change_state_side_effect_test.rb +41 -0
  87. data/test/unit/class_method_test.rb +38 -1
  88. data/test/unit/date_time_inspect_test.rb +1 -1
  89. data/test/unit/{expectation_raiser_test.rb → exception_raiser_test.rb} +14 -0
  90. data/test/unit/expectation_list_test.rb +4 -22
  91. data/test/unit/expectation_test.rb +70 -94
  92. data/test/unit/in_state_ordering_constraint_test.rb +43 -0
  93. data/test/unit/mock_test.rb +16 -37
  94. data/test/unit/mockery_test.rb +149 -0
  95. data/test/unit/{no_yield_test.rb → no_yields_test.rb} +0 -0
  96. data/test/unit/object_test.rb +6 -89
  97. data/test/unit/parameter_matchers/equals_test.rb +25 -0
  98. data/test/unit/parameter_matchers/has_entries_test.rb +22 -1
  99. data/test/unit/parameter_matchers/has_entry_test.rb +24 -2
  100. data/test/unit/parameter_matchers/has_key_test.rb +11 -0
  101. data/test/unit/parameter_matchers/has_value_test.rb +12 -0
  102. data/test/unit/parameter_matchers/regexp_matches_test.rb +1 -1
  103. data/test/unit/parameter_matchers/responds_with_test.rb +25 -0
  104. data/test/unit/parameter_matchers/stub_matcher.rb +4 -0
  105. data/test/unit/parameter_matchers/yaml_equivalent_test.rb +25 -0
  106. data/test/unit/single_return_value_test.rb +0 -19
  107. data/test/unit/state_machine_test.rb +98 -0
  108. metadata +108 -69
  109. data/lib/mocha/auto_verify.rb +0 -118
  110. data/lib/mocha/infinite_range.rb +0 -25
  111. data/lib/mocha/missing_expectation.rb +0 -17
  112. data/lib/mocha/setup_and_teardown.rb +0 -23
  113. data/lib/mocha/stub.rb +0 -18
  114. data/test/integration/stubba_integration_test.rb +0 -89
  115. data/test/unit/auto_verify_test.rb +0 -129
  116. data/test/unit/expectation_error_test.rb +0 -24
  117. data/test/unit/infinite_range_test.rb +0 -53
  118. data/test/unit/missing_expectation_test.rb +0 -42
  119. data/test/unit/setup_and_teardown_test.rb +0 -76
  120. data/test/unit/stub_test.rb +0 -24
@@ -4,7 +4,7 @@ module Mocha
4
4
 
5
5
  module ParameterMatchers
6
6
 
7
- # :call-seq: anything -> parameter_matcher
7
+ # :call-seq: anything() -> parameter_matcher
8
8
  #
9
9
  # Matches any object.
10
10
  # object = mock()
@@ -1,4 +1,6 @@
1
1
  require 'mocha/parameter_matchers/base'
2
+ require 'mocha/parameter_matchers/all_of'
3
+ require 'mocha/parameter_matchers/has_entry'
2
4
 
3
5
  module Mocha
4
6
 
@@ -28,7 +30,8 @@ module Mocha
28
30
 
29
31
  def matches?(available_parameters)
30
32
  parameter = available_parameters.shift
31
- @entries.all? { |key, value| parameter[key] == value }
33
+ has_entry_matchers = @entries.map { |key, value| HasEntry.new(key, value) }
34
+ AllOf.new(*has_entry_matchers).matches?([parameter])
32
35
  end
33
36
 
34
37
  def mocha_inspect
@@ -41,11 +41,12 @@ module Mocha
41
41
 
42
42
  def matches?(available_parameters)
43
43
  parameter = available_parameters.shift
44
- parameter[@key] == @value
44
+ matching_keys = parameter.keys.select { |key| @key.to_matcher.matches?([key]) }
45
+ matching_keys.any? { |key| @value.to_matcher.matches?([parameter[key]]) }
45
46
  end
46
47
 
47
48
  def mocha_inspect
48
- "has_entry(#{@key.mocha_inspect}, #{@value.mocha_inspect})"
49
+ "has_entry(#{@key.mocha_inspect} => #{@value.mocha_inspect})"
49
50
  end
50
51
 
51
52
  end
@@ -28,7 +28,7 @@ module Mocha
28
28
 
29
29
  def matches?(available_parameters)
30
30
  parameter = available_parameters.shift
31
- parameter.keys.include?(@key)
31
+ parameter.keys.any? { |key| @key.to_matcher.matches?([key]) }
32
32
  end
33
33
 
34
34
  def mocha_inspect
@@ -28,7 +28,7 @@ module Mocha
28
28
 
29
29
  def matches?(available_parameters)
30
30
  parameter = available_parameters.shift
31
- parameter.values.include?(@value)
31
+ parameter.values.any? { |value| @value.to_matcher.matches?([value]) }
32
32
  end
33
33
 
34
34
  def mocha_inspect
@@ -4,9 +4,9 @@ module Mocha
4
4
 
5
5
  module ParameterMatchers
6
6
 
7
- # :call-seq: Not(matcher) -> parameter_matcher
7
+ # :call-seq: Not(parameter_matcher) -> parameter_matcher
8
8
  #
9
- # Matches if +matcher+ does not match.
9
+ # Matches if +parameter_matcher+ does not match.
10
10
  # object = mock()
11
11
  # object.expects(:method_1).with(Not(includes(1)))
12
12
  # object.method_1([0, 2, 3])
@@ -2,7 +2,7 @@ require 'mocha/parameter_matchers/equals'
2
2
 
3
3
  class Object
4
4
 
5
- def to_matcher
5
+ def to_matcher # :nodoc:
6
6
  Mocha::ParameterMatchers::Equals.new(self)
7
7
  end
8
8
 
@@ -2,6 +2,28 @@ module Mocha
2
2
 
3
3
  module ParameterMatchers
4
4
 
5
+ # :call-seq: optionally(*parameter_matchers) -> parameter_matcher
6
+ #
7
+ # Matches optional parameters if available.
8
+ # object = mock()
9
+ # object.expects(:method_1).with(1, 2, optionally(3, 4))
10
+ # object.method_1(1, 2)
11
+ # # no error raised
12
+ #
13
+ # object = mock()
14
+ # object.expects(:method_1).with(1, 2, optionally(3, 4))
15
+ # object.method_1(1, 2, 3)
16
+ # # no error raised
17
+ #
18
+ # object = mock()
19
+ # object.expects(:method_1).with(1, 2, optionally(3, 4))
20
+ # object.method_1(1, 2, 3, 4)
21
+ # # no error raised
22
+ #
23
+ # object = mock()
24
+ # object.expects(:method_1).with(1, 2, optionally(3, 4))
25
+ # object.method_1(1, 2, 3, 5)
26
+ # # error raised, because optional parameters did not match
5
27
  def optionally(*matchers)
6
28
  Optionally.new(*matchers)
7
29
  end
@@ -4,9 +4,9 @@ module Mocha
4
4
 
5
5
  module ParameterMatchers
6
6
 
7
- # :call-seq: regexp_matches(regexp) -> parameter_matcher
7
+ # :call-seq: regexp_matches(regular_expression) -> parameter_matcher
8
8
  #
9
- # Matches any object that matches the regular expression, +regexp+.
9
+ # Matches any object that matches +regular_expression+.
10
10
  # object = mock()
11
11
  # object.expects(:method_1).with(regexp_matches(/e/))
12
12
  # object.method_1('hello')
@@ -0,0 +1,43 @@
1
+ require 'mocha/parameter_matchers/base'
2
+ require 'yaml'
3
+
4
+ module Mocha
5
+
6
+ module ParameterMatchers
7
+
8
+ # :call-seq: responds_with(message, result) -> parameter_matcher
9
+ #
10
+ # Matches any object that responds to +message+ with +result+. To put it another way, it tests the quack, not the duck.
11
+ # object = mock()
12
+ # object.expects(:method_1).with(responds_with(:upcase, "FOO"))
13
+ # object.method_1("foo")
14
+ # # no error raised, because "foo".upcase == "FOO"
15
+ #
16
+ # object = mock()
17
+ # object.expects(:method_1).with(responds_with(:upcase, "BAR"))
18
+ # object.method_1("foo")
19
+ # # error raised, because "foo".upcase != "BAR"
20
+ def responds_with(message, result)
21
+ RespondsWith.new(message, result)
22
+ end
23
+
24
+ class RespondsWith < Base # :nodoc:
25
+
26
+ def initialize(message, result)
27
+ @message, @result = message, result
28
+ end
29
+
30
+ def matches?(available_parameters)
31
+ parameter = available_parameters.shift
32
+ parameter.__send__(@message) == @result
33
+ end
34
+
35
+ def mocha_inspect
36
+ "responds_with(#{@message.mocha_inspect}, #{@result.mocha_inspect})"
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,43 @@
1
+ require 'mocha/parameter_matchers/base'
2
+ require 'yaml'
3
+
4
+ module Mocha
5
+
6
+ module ParameterMatchers
7
+
8
+ # :call-seq: yaml_equivalent(object) -> parameter_matcher
9
+ #
10
+ # Matches any YAML that represents the specified +object+
11
+ # object = mock()
12
+ # object.expects(:method_1).with(yaml_equivalent(1, 2, 3))
13
+ # object.method_1("--- \n- 1\n- 2\n- 3\n")
14
+ # # no error raised
15
+ #
16
+ # object = mock()
17
+ # object.expects(:method_1).with(yaml_equivalent(1, 2, 3))
18
+ # object.method_1("--- \n- 1\n- 2\n")
19
+ # # error raised, because method_1 was not called with YAML representing the specified Array
20
+ def yaml_equivalent(object)
21
+ YamlEquivalent.new(object)
22
+ end
23
+
24
+ class YamlEquivalent < Base # :nodoc:
25
+
26
+ def initialize(object)
27
+ @object = object
28
+ end
29
+
30
+ def matches?(available_parameters)
31
+ parameter = available_parameters.shift
32
+ @object == YAML.load(parameter)
33
+ end
34
+
35
+ def mocha_inspect
36
+ "yaml_equivalent(#{@object.mocha_inspect})"
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -1,5 +1,4 @@
1
1
  require 'mocha/is_a'
2
- require 'mocha/deprecation'
3
2
 
4
3
  module Mocha # :nodoc:
5
4
 
@@ -10,15 +9,9 @@ module Mocha # :nodoc:
10
9
  end
11
10
 
12
11
  def evaluate
13
- if @value.__is_a__(Proc) then
14
- message = 'use of Expectation#returns with instance of Proc - see Expectation#returns RDoc for alternatives'
15
- Deprecation.warning(message)
16
- @value.call
17
- else
18
- @value
19
- end
12
+ @value
20
13
  end
21
14
 
22
15
  end
23
16
 
24
- end
17
+ end
@@ -1,32 +1,166 @@
1
- require 'mocha/auto_verify'
2
1
  require 'mocha/parameter_matchers'
3
- require 'mocha/setup_and_teardown'
2
+ require 'mocha/mockery'
3
+ require 'mocha/sequence'
4
4
 
5
- module Mocha
5
+ module Mocha # :nodoc:
6
6
 
7
+ # Methods added to Test::Unit::TestCase or equivalent.
7
8
  module Standalone
8
9
 
9
- include AutoVerify
10
10
  include ParameterMatchers
11
- include SetupAndTeardown
12
11
 
13
- def mocha_setup
14
- setup_stubs
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
15
46
  end
16
47
 
17
- def mocha_verify(&block)
18
- verify_mocks(&block)
19
- verify_stubs(&block)
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
20
81
  end
21
82
 
22
- def mocha_teardown
23
- begin
24
- teardown_mocks
25
- ensure
26
- teardown_stubs
27
- end
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
28
162
  end
29
163
 
30
164
  end
31
165
 
32
- end
166
+ end
@@ -0,0 +1,91 @@
1
+ module Mocha # :nodoc:
2
+
3
+ # A state machine that is used to constrain the order of invocations.
4
+ # An invocation can be constrained to occur when a state is, or is_not, active.
5
+ class StateMachine
6
+
7
+ class State # :nodoc:
8
+
9
+ def initialize(state_machine, state)
10
+ @state_machine, @state = state_machine, state
11
+ end
12
+
13
+ def activate
14
+ @state_machine.current_state = @state
15
+ end
16
+
17
+ def active?
18
+ @state_machine.current_state == @state
19
+ end
20
+
21
+ def mocha_inspect
22
+ "#{@state_machine.name} is #{@state.mocha_inspect}"
23
+ end
24
+
25
+ end
26
+
27
+ class StatePredicate # :nodoc:
28
+
29
+ def initialize(state_machine, state)
30
+ @state_machine, @state = state_machine, state
31
+ end
32
+
33
+ def active?
34
+ @state_machine.current_state != @state
35
+ end
36
+
37
+ def mocha_inspect
38
+ "#{@state_machine.name} is not #{@state.mocha_inspect}"
39
+ end
40
+
41
+ end
42
+
43
+ attr_reader :name # :nodoc:
44
+
45
+ attr_accessor :current_state # :nodoc:
46
+
47
+ def initialize(name) # :nodoc:
48
+ @name = name
49
+ @current_state = nil
50
+ end
51
+
52
+ # :call-seq: starts_as(initial_state) -> state_machine
53
+ #
54
+ # Put the +state_machine+ into the +initial_state+.
55
+ def starts_as(initial_state)
56
+ become(initial_state)
57
+ self
58
+ end
59
+
60
+ # :call-seq: become(next_state)
61
+ #
62
+ # Put the +state_machine+ into the +next_state+.
63
+ def become(next_state)
64
+ @current_state = next_state
65
+ end
66
+
67
+ # :call-seq: is(state)
68
+ #
69
+ # Determines whether the +state_machine+ is in the specified +state+.
70
+ def is(state)
71
+ State.new(self, state)
72
+ end
73
+
74
+ # :call-seq: is_not(state)
75
+ #
76
+ # Determines whether the +state_machine+ is not in the specified +state+.
77
+ def is_not(state)
78
+ StatePredicate.new(self, state)
79
+ end
80
+
81
+ def mocha_inspect # :nodoc:
82
+ if @current_state
83
+ "#{@name} is #{@current_state.mocha_inspect}"
84
+ else
85
+ "#{@name} has no current state"
86
+ end
87
+ end
88
+
89
+ end
90
+
91
+ end