From 4e28497a0df59b86537cdc689ef3cd11ea6c7c3e Mon Sep 17 00:00:00 2001 From: James Mead Date: Sat, 31 Mar 2012 18:27:57 +0100 Subject: [PATCH] Generate documentation using YARD instead of RDoc. - YARD allows for much richer documentation. - It looks prettier too. - I hope to remove the dependencies on rdoc & coderay. --- COPYING.rdoc | 2 +- README.rdoc | 8 +- Rakefile | 43 +-- lib/mocha/api.rb | 226 ++++++++-------- lib/mocha/configuration.rb | 83 +++--- lib/mocha/expectation.rb | 250 ++++++++++++------ lib/mocha/mock.rb | 139 ++++++---- lib/mocha/object.rb | 167 ++++++------ lib/mocha/parameter_matchers.rb | 6 +- lib/mocha/parameter_matchers/all_of.rb | 34 ++- lib/mocha/parameter_matchers/any_of.rb | 35 ++- .../parameter_matchers/any_parameters.rb | 23 +- lib/mocha/parameter_matchers/anything.rb | 31 ++- lib/mocha/parameter_matchers/base.rb | 60 +++-- lib/mocha/parameter_matchers/equals.rb | 35 ++- lib/mocha/parameter_matchers/has_entries.rb | 34 ++- lib/mocha/parameter_matchers/has_entry.rb | 44 ++- lib/mocha/parameter_matchers/has_key.rb | 32 ++- lib/mocha/parameter_matchers/has_value.rb | 32 ++- lib/mocha/parameter_matchers/includes.rb | 18 +- lib/mocha/parameter_matchers/instance_of.rb | 35 ++- lib/mocha/parameter_matchers/is_a.rb | 35 ++- lib/mocha/parameter_matchers/kind_of.rb | 35 ++- lib/mocha/parameter_matchers/not.rb | 34 ++- lib/mocha/parameter_matchers/object.rb | 8 +- lib/mocha/parameter_matchers/optionally.rb | 36 ++- lib/mocha/parameter_matchers/query_string.rb | 17 +- .../parameter_matchers/regexp_matches.rb | 30 ++- lib/mocha/parameter_matchers/responds_with.rb | 23 +- .../parameter_matchers/yaml_equivalent.rb | 22 +- lib/mocha/sequence.rb | 37 ++- lib/mocha/state_machine.rb | 107 ++++---- lib/mocha/stubbing_error.rb | 9 +- mocha.gemspec | 3 + 34 files changed, 1070 insertions(+), 663 deletions(-) diff --git a/COPYING.rdoc b/COPYING.rdoc index 6bed2d9c3..d4de035c3 100644 --- a/COPYING.rdoc +++ b/COPYING.rdoc @@ -1,3 +1,3 @@ Copyright Revieworld Ltd. 2006 -You may use, copy and redistribute this library under the same terms as {Ruby itself}[http://www.ruby-lang.org/en/LICENSE.txt] or under the {MIT license}[/files/MIT-LICENSE.rdoc.html]. \ No newline at end of file +You may use, copy and redistribute this library under the same terms as {Ruby itself}[http://www.ruby-lang.org/en/LICENSE.txt] or under the {file:MIT-LICENSE.rdoc MIT license}. \ No newline at end of file diff --git a/README.rdoc b/README.rdoc index 1f8c3cc98..0758ca9ee 100644 --- a/README.rdoc +++ b/README.rdoc @@ -36,9 +36,9 @@ Note that versions 0.9.6 & 0.9.7 of the Rails plugin were broken. As of version == Examples -* Quick Start - {Usage Examples}[/examples/misc.html] -* Traditional mocking - {Star Trek Example}[/examples/mocha.html] -* Setting expectations on real classes - {Order Example}[/examples/stubba.html] +* Quick Start - {file:misc.rb Usage Examples} +* Traditional mocking - {file:mocha.rb Star Trek Example} +* Setting expectations on real classes - {file:stubba.rb Order Example} * More examples on {James Mead's Blog}[http://jamesmead.org/blog/] * {Mailing List Archives}[http://groups.google.com/group/mocha-developer] @@ -51,4 +51,4 @@ Note that versions 0.9.6 & 0.9.7 of the Rails plugin were broken. As of version Copyright Revieworld Ltd. 2006 -You may use, copy and redistribute this library under the same terms as {Ruby itself}[http://www.ruby-lang.org/en/LICENSE.txt] or under the {MIT license}[/files/MIT-LICENSE.rdoc.html]. +You may use, copy and redistribute this library under the same terms as {Ruby itself}[http://www.ruby-lang.org/en/LICENSE.txt] or under the {file:MIT-LICENSE.rdoc MIT license}. diff --git a/Rakefile b/Rakefile index e45505c5e..f64fb3930 100644 --- a/Rakefile +++ b/Rakefile @@ -2,7 +2,7 @@ require "bundler" Bundler::GemHelper.install_tasks require "bundler/setup" -require 'rdoc/task' +require 'yard' require 'rake/testtask' desc "Run all tests" @@ -81,23 +81,15 @@ def benchmark_test_case(klass, iterations) end end -desc 'Generate RDoc' -Rake::RDocTask.new('rdoc') do |task| - task.generator = 'hanna' - task.main = 'README.rdoc' - task.title = "Mocha #{Mocha::VERSION}" - task.rdoc_dir = 'doc' - template = File.expand_path(File.join(File.dirname(__FILE__), "templates", "html_with_google_analytics.rb")) - if File.exist?(template) - puts "*** Using RDoc template incorporating Google Analytics" - task.template = template - end - task.rdoc_files.include( - 'README.rdoc', - 'RELEASE.rdoc', - 'COPYING.rdoc', - 'MIT-LICENSE.rdoc', - 'agiledox.txt', +desc 'Remove generated documentation' +task 'clobber_yardoc' do + `rm -rf ./doc` +end + +desc 'Generate documentation' +YARD::Rake::YardocTask.new('yardoc') do |task| + task.options = ["--title", "Mocha #{Mocha::VERSION}", "--no-private"] + task.files = [ 'lib/mocha/api.rb', 'lib/mocha/mock.rb', 'lib/mocha/expectation.rb', @@ -105,13 +97,22 @@ Rake::RDocTask.new('rdoc') do |task| 'lib/mocha/parameter_matchers.rb', 'lib/mocha/parameter_matchers', 'lib/mocha/state_machine.rb', + 'lib/mocha/sequence.rb', 'lib/mocha/configuration.rb', - 'lib/mocha/stubbing_error.rb' - ) + 'lib/mocha/stubbing_error.rb', + '-', + 'RELEASE.rdoc', + 'COPYING.rdoc', + 'MIT-LICENSE.rdoc', + 'agiledox.txt', + 'examples/mocha.rb', + 'examples/stubba.rb', + 'examples/misc.rb', + ] end desc "Generate documentation" -task 'generate_docs' => ['clobber_rdoc', 'rdoc', 'examples', 'agiledox.txt'] +task 'generate_docs' => ['clobber_yardoc', 'agiledox.txt', 'yardoc'] desc "Publish docs to Github (relies on running 'generate_docs' task and committing changes to master branch)" task 'publish_docs' do diff --git a/lib/mocha/api.rb b/lib/mocha/api.rb index 863175b90..80a8f9433 100644 --- a/lib/mocha/api.rb +++ b/lib/mocha/api.rb @@ -2,40 +2,40 @@ require 'mocha/mockery' require 'mocha/sequence' -module Mocha # :nodoc: - - # Methods added to Test::Unit::TestCase or equivalent. +module Mocha + + # Methods added to +Test::Unit::TestCase+ or equivalent. module API - + include ParameterMatchers - - # :call-seq: mock(name, &block) -> mock object - # mock(expected_methods = {}, &block) -> mock object - # mock(name, expected_methods = {}, &block) -> mock object - # - # Creates a mock object. - # - # +name+ is a +String+ identifier for the mock object. - # - # +expected_methods+ is a +Hash+ with expected method name symbols as keys and corresponding return values as values. - # - # Note that (contrary to expectations set up by #stub) these expectations must be fulfilled during the test. - # def test_product - # product = mock('ipod_product', :manufacturer => 'ipod', :price => 100) - # assert_equal 'ipod', product.manufacturer - # assert_equal 100, product.price - # # an error will be raised unless both Product#manufacturer and Product#price have been called - # end - # - # +block+ is an optional block to be evaluated against the mock object instance, giving an alernative way to set up expectations & stubs. - # def test_product - # product = mock('ipod_product') do - # expects(:manufacturer).returns('ipod') - # expects(:price).returns(100) + + # Builds a new mock object + # + # @param [String] name identifies mock object in error messages. + # @param [Hash] expected_methods_vs_return_values expected method name symbols as keys and corresponding return values as values - these expectations are setup as if {Mock#expects} were called multiple times. + # @yield optional block to be evaluated against the mock object instance, giving an alternative way to setup expectations. + # @return [Mock] a new mock object + # + # @overload def mock(name, &block) + # @overload def mock(expected_methods_vs_return_values = {}, &block) + # @overload def mock(name, expected_methods_vs_return_values = {}, &block) + # + # @example Using expected_methods_vs_return_values Hash to setup expectations. + # def test_motor_starts_and_stops + # motor = mock('motor', :start => true, :stop => true) + # assert motor.start + # assert motor.stop + # # an error will be raised unless both Motor#start and Motor#stop have been called + # end + # @example Using the optional block to setup expectations & stubbed methods. + # def test_motor_starts_and_stops + # motor = mock('motor') do + # expects(:start).with(100.rpm).returns(true) + # stubs(:stop).returns(true) # end - # assert_equal 'ipod', product.manufacturer - # assert_equal 100, product.price - # # an error will be raised unless both Product#manufacturer and Product#price have been called + # assert motor.start(100.rpm) + # assert motor.stop + # # an error will only be raised if Motor#start(100.rpm) has not been called # end def mock(*arguments, &block) name = arguments.shift if arguments.first.is_a?(String) @@ -44,34 +44,36 @@ def mock(*arguments, &block) mock.expects(expectations) mock end - - # :call-seq: stub(name, &block) -> mock object - # stub(stubbed_methods = {}, &block) -> mock object - # stub(name, stubbed_methods = {}, &block) -> mock object - # - # Creates a mock object. - # - # +name+ is a +String+ identifier for the mock object. - # - # +stubbed_methods+ is a +Hash+ with stubbed method name symbols as keys and corresponding return values as values. - # Note that (contrary to expectations set up by #mock) these expectations need not be fulfilled during the test. - # def test_product - # product = stub('ipod_product', :manufacturer => 'ipod', :price => 100) - # assert_equal 'ipod', product.manufacturer - # assert_equal 100, product.price - # # an error will not be raised even if Product#manufacturer and Product#price have not been called + + # Builds a new mock object + # + # @param [String] name identifies mock object in error messages. + # @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {Mock#stubs} were called multiple times. + # @yield optional block to be evaluated against the mock object instance, giving an alternative way to setup stubbed methods. + # @return [Mock] a new mock object + # + # @overload def stub(name, &block) + # @overload def stub(stubbed_methods_vs_return_values = {}, &block) + # @overload def stub(name, stubbed_methods_vs_return_values = {}, &block) + # + # @example Using stubbed_methods_vs_return_values Hash to setup stubbed methods. + # def test_motor_starts_and_stops + # motor = mock('motor', :start => true, :stop => true) + # assert motor.start + # assert motor.stop + # # an error will not be raised even if either Motor#start or Motor#stop has not been called # end # - # +block+ is an optional block to be evaluated against the mock object instance, giving an alernative way to set up expectations & stubs. - # def test_product - # product = stub('ipod_product') do - # stubs(:manufacturer).returns('ipod') - # stubs(:price).returns(100) + # @example Using the optional block to setup expectations & stubbed methods. + # def test_motor_starts_and_stops + # motor = mock('motor') do + # expects(:start).with(100.rpm).returns(true) + # stubs(:stop).returns(true) # end - # assert_equal 'ipod', product.manufacturer - # assert_equal 100, product.price - # # an error will not be raised even if Product#manufacturer and Product#price have not been called - # end + # assert motor.start(100.rpm) + # assert motor.stop + # # an error will only be raised if Motor#start(100.rpm) has not been called + # end def stub(*arguments, &block) name = arguments.shift if arguments.first.is_a?(String) expectations = arguments.shift || {} @@ -79,23 +81,24 @@ def stub(*arguments, &block) stub.stubs(expectations) stub end - - # :call-seq: stub_everything(name, &block) -> mock object - # stub_everything(stubbed_methods = {}, &block) -> mock object - # stub_everything(name, stubbed_methods = {}, &block) -> mock object - # - # Creates a mock object that accepts calls to any method. - # - # By default it will return +nil+ for any method call. - # - # +block+ is a block to be evaluated against the mock object instance, giving an alernative way to set up expectations & stubs. - # - # +name+ and +stubbed_methods+ work in the same way as for #stub. - # def test_product - # product = stub_everything('ipod_product', :price => 100) - # assert_nil product.manufacturer - # assert_nil product.any_old_method - # assert_equal 100, product.price + + # Builds a mock object that accepts calls to any method. By default it will return +nil+ for any method call. + # + # @param [String] name identifies mock object in error messages. + # @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {Mock#stubs} were called multiple times. + # @yield optional block to be evaluated against the mock object instance, giving an alternative way to setup stubbed methods. + # @return [Mock] a new mock object + # + # @overload def stub_everything(name, &block) + # @overload def stub_everything(stubbed_methods_vs_return_values = {}, &block) + # @overload def stub_everything(name, stubbed_methods_vs_return_values = {}, &block) + # + # @example Ignore invocations of irrelevant methods. + # def test_motor_stops + # motor = stub_everything('motor', :stop => true) + # assert_nil motor.irrelevant_method_1 # => no error raised + # assert_nil motor.irrelevant_method_2 # => no error raised + # assert motor.stop # end def stub_everything(*arguments, &block) name = arguments.shift if arguments.first.is_a?(String) @@ -105,69 +108,80 @@ def stub_everything(*arguments, &block) stub.stubs(expectations) stub end - - # :call-seq: sequence(name) -> sequence + + # Builds a new sequence which can be used to constrain the order in which expectations can occur. # - # Returns a new sequence that is used to constrain the order in which expectations can occur. + # Specify that an expected invocation must occur within a named {Sequence} by using {Expectation#in_sequence}. # - # Specify that an expected invocation must occur in within a named +sequence+ by using Expectation#in_sequence. + # @return [Sequence] a new sequence # - # See also Expectation#in_sequence. + # @see Expectation#in_sequence + # + # @example Ensure methods on egg are invoked in correct order. # breakfast = sequence('breakfast') # - # egg = mock('egg') - # egg.expects(:crack).in_sequence(breakfast) - # egg.expects(:fry).in_sequence(breakfast) - # egg.expects(:eat).in_sequence(breakfast) + # egg = mock('egg') do + # expects(:crack).in_sequence(breakfast) + # expects(:fry).in_sequence(breakfast) + # expects(:eat).in_sequence(breakfast) + # end def sequence(name) Sequence.new(name) end - - # :call-seq: states(name) -> state_machine + + # Builds a new state machine which can be used to constrain the order in which expectations can occur. # - # Returns a new +state_machine+ that is used to constrain the order in which expectations can occur. + # Specify the initial state of the state machine by using {StateMachine#starts_as}. # - # Specify the initial +state+ of the +state_machine+ by using StateMachine#starts_as. + # Specify that an expected invocation should change the state of the state machine by using {Expectation#then}. # - # Specify that an expected invocation should change the +state+ of the +state_machine+ by using Expectation#then. + # Specify that an expected invocation should be constrained to occur within a particular +state+ by using {Expectation#when}. # - # Specify that an expected invocation should be constrained to occur within a particular +state+ by using Expectation#when. + # A test can contain multiple state machines. # - # A test can contain multiple +state_machines+. + # @return [StateMachine] a new state machine # - # See also Expectation#then, Expectation#when and StateMachine. + # @see Expectation#then + # @see Expectation#when + # @see StateMachine + # @example Constrain expected invocations to occur in particular states. # power = states('power').starts_as('off') # - # radio = mock('radio') - # radio.expects(:switch_on).then(power.is('on')) - # radio.expects(:select_channel).with('BBC Radio 4').when(power.is('on')) - # radio.expects(:adjust_volume).with(+5).when(power.is('on')) - # radio.expects(:select_channel).with('BBC World Service').when(power.is('on')) - # radio.expects(:adjust_volume).with(-5).when(power.is('on')) - # radio.expects(:switch_off).then(power.is('off')) + # radio = mock('radio') do + # expects(:switch_on).then(power.is('on')) + # expects(:select_channel).with('BBC Radio 4').when(power.is('on')) + # expects(:adjust_volume).with(+5).when(power.is('on')) + # expects(:select_channel).with('BBC World Service').when(power.is('on')) + # expects(:adjust_volume).with(-5).when(power.is('on')) + # expects(:switch_off).then(power.is('off')) + # end def states(name) Mockery.instance.new_state_machine(name) end - - def mocha_setup # :nodoc: + + # @private + def mocha_setup end - - def mocha_verify(assertion_counter = nil) # :nodoc: + + # @private + def mocha_verify(assertion_counter = nil) Mockery.instance.verify(assertion_counter) end - - def mocha_teardown # :nodoc: + + # @private + def mocha_teardown Mockery.instance.teardown Mockery.reset_instance end - + end - + + # @private def self.const_missing(name) return super unless name == :Standalone require 'mocha/deprecation' Deprecation.warning "Mocha::Standalone has been renamed to Mocha::API" return API end - + end diff --git a/lib/mocha/configuration.rb b/lib/mocha/configuration.rb index 6c6234229..bf8620faa 100644 --- a/lib/mocha/configuration.rb +++ b/lib/mocha/configuration.rb @@ -1,62 +1,70 @@ -module Mocha # :nodoc: - - # Configuration settings +module Mocha + + # Configuration settings. class Configuration - - DEFAULTS = { :stubbing_method_unnecessarily => :allow, :stubbing_method_on_non_mock_object => :allow, :stubbing_non_existent_method => :allow, :stubbing_non_public_method => :allow } - + + DEFAULTS = { + :stubbing_method_unnecessarily => :allow, + :stubbing_method_on_non_mock_object => :allow, + :stubbing_non_existent_method => :allow, + :stubbing_non_public_method => :allow + } + class << self - - # :call-seq: allow(action, &block) + + # Allow the specified +action+. # - # Allow the specified action (as a symbol). - # The actions currently available are :stubbing_method_unnecessarily, :stubbing_method_on_non_mock_object, :stubbing_non_existent_method, :stubbing_non_public_method. - # If given a block, the configuration for the action will only be changed for the duration of the block, and will then be restored to the previous value. + # @param [Symbol] action one of +:stubbing_method_unnecessarily+, +:stubbing_method_on_non_mock_object+, +:stubbing_non_existent_method+, +:stubbing_non_public_method+. + # @yield optional block during which the configuration change will be changed before being returned to its original value at the end of the block. def allow(action, &block) change_config action, :allow, &block end - - def allow?(action) # :nodoc: + + # @private + def allow?(action) configuration[action] == :allow end - - # :call-seq: warn_when(action, &block) + + # Warn if the specified +action+ is attempted. # - # Warn if the specified action (as a symbol) is attempted. - # The actions currently available are :stubbing_method_unnecessarily, :stubbing_method_on_non_mock_object, :stubbing_non_existent_method, :stubbing_non_public_method. - # If given a block, the configuration for the action will only be changed for the duration of the block, and will then be restored to the previous value. + # @param [Symbol] action one of +:stubbing_method_unnecessarily+, +:stubbing_method_on_non_mock_object+, +:stubbing_non_existent_method+, +:stubbing_non_public_method+. + # @yield optional block during which the configuration change will be changed before being returned to its original value at the end of the block. def warn_when(action, &block) change_config action, :warn, &block end - - def warn_when?(action) # :nodoc: + + # @private + def warn_when?(action) configuration[action] == :warn end - - # :call-seq: prevent(action, &block) + + # Raise a {StubbingError} if if the specified +action+ is attempted. # - # Raise a StubbingError if the specified action (as a symbol) is attempted. - # The actions currently available are :stubbing_method_unnecessarily, :stubbing_method_on_non_mock_object, :stubbing_non_existent_method, :stubbing_non_public_method. - # If given a block, the configuration for the action will only be changed for the duration of the block, and will then be restored to the previous value. + # @param [Symbol] action one of +:stubbing_method_unnecessarily+, +:stubbing_method_on_non_mock_object+, +:stubbing_non_existent_method+, +:stubbing_non_public_method+. + # @yield optional block during which the configuration change will be changed before being returned to its original value at the end of the block. def prevent(action, &block) change_config action, :prevent, &block end - - def prevent?(action) # :nodoc: + + # @private + def prevent?(action) configuration[action] == :prevent end - - def reset_configuration # :nodoc: + + # @private + def reset_configuration @configuration = nil end - + private - - def configuration # :nodoc: + + # @private + def configuration @configuration ||= DEFAULTS.dup end - def change_config(action, new_value, &block) # :nodoc: + # @private + def change_config(action, new_value, &block) if block_given? temporarily_change_config action, new_value, &block else @@ -64,16 +72,17 @@ def change_config(action, new_value, &block) # :nodoc: end end - def temporarily_change_config(action, new_value, &block) # :nodoc: + # @private + def temporarily_change_config(action, new_value, &block) original_value = configuration[action] configuration[action] = new_value yield ensure configuration[action] = original_value end - + end - + end - + end diff --git a/lib/mocha/expectation.rb b/lib/mocha/expectation.rb index 0886d149b..a0cd34eae 100644 --- a/lib/mocha/expectation.rb +++ b/lib/mocha/expectation.rb @@ -10,16 +10,17 @@ require 'mocha/change_state_side_effect' require 'mocha/cardinality' -module Mocha # :nodoc: +module Mocha - # Methods on expectations returned from Mock#expects, Mock#stubs, Object#expects and Object#stubs. + # Methods on expectations returned from {Mock#expects}, {Mock#stubs}, {ObjectMethods#expects} and {ObjectMethods#stubs}. class Expectation - # :call-seq: times(range) -> expectation - # # Modifies expectation so that the number of calls to the expected method must be within a specific +range+. # - # +range+ can be specified as an exact integer or as a range of integers + # @param [Range,Integer] range specifies the allowable range in the number of expected invocations. + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. + # + # @example Specifying a specific number of expected invocations. # object = mock() # object.expects(:expected_method).times(3) # 3.times { object.expected_method } @@ -30,6 +31,7 @@ class Expectation # 2.times { object.expected_method } # # => verify fails # + # @example Specifying a range in the number of expected invocations. # object = mock() # object.expects(:expected_method).times(2..4) # 3.times { object.expected_method } @@ -44,9 +46,11 @@ def times(range) self end - # :call-seq: twice() -> expectation - # # Modifies expectation so that the expected method must be called exactly twice. + # + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. + # + # @example Expected method must be invoked exactly twice. # object = mock() # object.expects(:expected_method).twice # object.expected_method @@ -57,8 +61,7 @@ def times(range) # object.expects(:expected_method).twice # object.expected_method # object.expected_method - # object.expected_method - # # => verify fails + # object.expected_method # => unexpected invocation # # object = mock() # object.expects(:expected_method).twice @@ -69,10 +72,13 @@ def twice self end - # :call-seq: once() -> expectation - # # Modifies expectation so that the expected method must be called exactly once. + # # Note that this is the default behaviour for an expectation, but you may wish to use it for clarity/emphasis. + # + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. + # + # @example Expected method must be invoked exactly once. # object = mock() # object.expects(:expected_method).once # object.expected_method @@ -81,8 +87,7 @@ def twice # object = mock() # object.expects(:expected_method).once # object.expected_method - # object.expected_method - # # => verify fails + # object.expected_method # => unexpected invocation # # object = mock() # object.expects(:expected_method).once @@ -92,13 +97,14 @@ def once self end - # :call-seq: never() -> expectation - # # Modifies expectation so that the expected method must never be called. + # + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. + # + # @example Expected method must never be called. # object = mock() # object.expects(:expected_method).never - # object.expected_method - # # => verify fails + # object.expected_method # => unexpected invocation # # object = mock() # object.expects(:expected_method).never @@ -108,9 +114,12 @@ def never self end - # :call-seq: at_least(minimum_number_of_times) -> expectation - # # Modifies expectation so that the expected method must be called at least a +minimum_number_of_times+. + # + # @param [Integer] minimum_number_of_times minimum number of expected invocations. + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. + # + # @example Expected method must be called at least twice. # object = mock() # object.expects(:expected_method).at_least(2) # 3.times { object.expected_method } @@ -125,9 +134,11 @@ def at_least(minimum_number_of_times) self end - # :call-seq: at_least_once() -> expectation - # # Modifies expectation so that the expected method must be called at least once. + # + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. + # + # @example Expected method must be called at least once. # object = mock() # object.expects(:expected_method).at_least_once # object.expected_method @@ -141,9 +152,12 @@ def at_least_once self end - # :call-seq: at_most(maximum_number_of_times) -> expectation - # # Modifies expectation so that the expected method must be called at most a +maximum_number_of_times+. + # + # @param [Integer] maximum_number_of_times maximum number of expected invocations. + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. + # + # @example Expected method must be called at most twice. # object = mock() # object.expects(:expected_method).at_most(2) # 2.times { object.expected_method } @@ -151,16 +165,17 @@ def at_least_once # # object = mock() # object.expects(:expected_method).at_most(2) - # 3.times { object.expected_method } - # # => verify fails + # 3.times { object.expected_method } # => unexpected invocation def at_most(maximum_number_of_times) @cardinality = Cardinality.at_most(maximum_number_of_times) self end - # :call-seq: at_most_once() -> expectation - # # Modifies expectation so that the expected method must be called at most once. + # + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. + # + # @example Expected method must be called at most once. # object = mock() # object.expects(:expected_method).at_most_once # object.expected_method @@ -168,16 +183,23 @@ def at_most(maximum_number_of_times) # # object = mock() # object.expects(:expected_method).at_most_once - # 2.times { object.expected_method } - # # => verify fails + # 2.times { object.expected_method } # => unexpected invocation def at_most_once() at_most(1) self end - # :call-seq: with(*expected_parameters, &matching_block) -> expectation - # # Modifies expectation so that the expected method must be called with +expected_parameters+. + # + # May be used with parameter matchers in {ParameterMatchers}. + # + # @param [*Array] expected_parameters parameters expected. + # @yield optional block specifying custom matching. + # @yieldparam [*Array] actual_parameters parameters with which expected method was invoked. + # @yieldreturn [Boolean] +true+ if +actual_parameters+ are acceptable. + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. + # + # @example Expected method must be called with expected parameters. # object = mock() # object.expects(:expected_method).with(:param1, :param2) # object.expected_method(:param1, :param2) @@ -187,10 +209,8 @@ def at_most_once() # object.expects(:expected_method).with(:param1, :param2) # object.expected_method(:param3) # # => verify fails - # May be used with parameter matchers in Mocha::ParameterMatchers. # - # If a +matching_block+ is given, the block is called with the parameters passed to the expected method. - # The expectation is matched if the block evaluates to +true+. + # @example Expected method must be called with a value divisible by 4. # object = mock() # object.expects(:expected_method).with() { |value| value % 4 == 0 } # object.expected_method(16) @@ -205,15 +225,22 @@ def with(*expected_parameters, &matching_block) self end - # :call-seq: yields(*parameters) -> expectation - # # Modifies expectation so that when the expected method is called, it yields with the specified +parameters+. + # + # May be called multiple times on the same expectation for consecutive invocations. + # + # @param [*Array] parameters parameters to be yielded. + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. + # @see #then + # + # @example Yield parameters when expected method is invoked. # object = mock() # object.expects(:expected_method).yields('result') # yielded_value = nil # object.expected_method { |value| yielded_value = value } # yielded_value # => 'result' - # May be called multiple times on the same expectation for consecutive invocations. Also see Expectation#then. + # + # @example Yield different parameters on different invocations of the expected method. # object = mock() # object.stubs(:expected_method).yields(1).then.yields(2) # yielded_values_from_first_invocation = [] @@ -227,18 +254,20 @@ def yields(*parameters) self end - # :call-seq: multiple_yields(*parameter_groups) -> expectation - # # Modifies expectation so that when the expected method is called, it yields multiple times per invocation with the specified +parameter_groups+. # - # Note that each +parameter_group+ should be an Array representing the parameters to be passed to the block for a single yield. In the following example when the expected_method is called, the stub will invoke the block twice, the first time it passes 'result_1', 'result_2' as the parameters, and the second time it passes 'result_3' as the parameters. + # @param [*Array] parameter_groups each element of +parameter_groups+ should iself be an +Array+ representing the parameters to be passed to the block for a single yield. + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. + # @see #then # + # @example When the +expected_method+ is called, the stub will invoke the block twice, the first time it passes +'result_1'+, +'result_2'+ as the parameters, and the second time it passes 'result_3' as the parameters. # object = mock() # object.expects(:expected_method).multiple_yields(['result_1', 'result_2'], ['result_3']) # yielded_values = [] # object.expected_method { |*values| yielded_values << values } # yielded_values # => [['result_1', 'result_2'], ['result_3]] - # May be called multiple times on the same expectation for consecutive invocations. Also see Expectation#then. + # + # @example Yield different groups of parameters on different invocations of the expected method. # object = mock() # object.stubs(:expected_method).multiple_yields([1, 2], [3]).then.multiple_yields([4], [5, 6]) # yielded_values_from_first_invocation = [] @@ -252,32 +281,43 @@ def multiple_yields(*parameter_groups) self end - # :call-seq: returns(value) -> expectation - # returns(*values) -> expectation - # # Modifies expectation so that when the expected method is called, it returns the specified +value+. + # + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. + # @see #then + # + # @overload def returns(value) + # @param [Object] value value to return on invocation of expected method. + # @overload def returns(*values) + # @param [*Array] values values to return on consecutive invocations of expected method. + # + # @example Return the same value on every invocation. # object = mock() # object.stubs(:stubbed_method).returns('result') # object.stubbed_method # => 'result' # object.stubbed_method # => 'result' - # If multiple +values+ are given, these are returned in turn on consecutive calls to the method. + # + # @example Return a different value on consecutive invocations. # object = mock() # object.stubs(:stubbed_method).returns(1, 2) # object.stubbed_method # => 1 # object.stubbed_method # => 2 - # May be called multiple times on the same expectation. Also see Expectation#then. + # + # @example Alternative way to return a different value on consecutive invocations. # object = mock() # object.stubs(:expected_method).returns(1, 2).then.returns(3) # object.expected_method # => 1 # object.expected_method # => 2 # object.expected_method # => 3 - # May be called in conjunction with Expectation#raises on the same expectation. + # + # @example May be called in conjunction with {#raises} on the same expectation. # object = mock() # object.stubs(:expected_method).returns(1, 2).then.raises(Exception) # object.expected_method # => 1 # object.expected_method # => 2 # object.expected_method # => raises exception of class Exception1 - # Note that in Ruby a method returning multiple values is exactly equivalent to a method returning an Array of those values. + # + # @example Note that in Ruby a method returning multiple values is exactly equivalent to a method returning an +Array+ of those values. # object = mock() # object.stubs(:expected_method).returns([1, 2]) # x, y = object.expected_method @@ -288,22 +328,36 @@ def returns(*values) self end - # :call-seq: raises(exception = RuntimeError, message = nil) -> expectation + # Modifies expectation so that when the expected method is called, it raises the specified +exception+ with the specified +message+ i.e. calls +Kernel#raise(exception, message)+. + # + # @param [Class,Exception,String,#exception] exception exception to be raised or message to be passed to RuntimeError. + # @param [String] message exception message. + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. + # + # @see Kernel#raise + # @see #then # - # Modifies expectation so that when the expected method is called, it raises the specified +exception+ with the specified +message+ i.e. calls Kernel#raise(exception, message). + # @overload def raises + # @overload def raises(exception) + # @overload def raises(exception, message) + # + # @example Raise specified exception if expected method is invoked. # object = stub() # object.stubs(:expected_method).raises(Exception, 'message') # object.expected_method # => raises exception of class Exception and with message 'message' - # Note that if you have a custom exception class with extra constructor parameters, you can pass in an instance of the exception (just as you can for Kernel#raise). + # + # @example Raise custom exception with extra constructor parameters by passing in an instance of the exception. # object = stub() # object.stubs(:expected_method).raises(MyException.new('message', 1, 2, 3)) # object.expected_method # => raises the specified instance of MyException - # May be called multiple times on the same expectation. Also see Expectation#then. + # + # @example Raise different exceptions on consecutive invocations of the expected method. # object = stub() # object.stubs(:expected_method).raises(Exception1).then.raises(Exception2) # object.expected_method # => raises exception of class Exception1 # object.expected_method # => raises exception of class Exception2 - # May be called in conjunction with Expectation#returns on the same expectation. + # + # @example Raise an exception on first invocation of expected method and then return values on subsequent invocations. # object = stub() # object.stubs(:expected_method).raises(Exception).then.returns(2, 3) # object.expected_method # => raises exception of class Exception1 @@ -314,22 +368,35 @@ def raises(exception = RuntimeError, message = nil) self end - # :call-seq: throws(tag, object = nil) -> expectation + # Modifies expectation so that when the expected method is called, it throws the specified +tag+ with the specific return value +object+ i.e. calls +Kernel#throw(tag, object)+. + # + # @param [Symbol,String] tag tag to throw to transfer control to the active catch block. + # @param [Object] object return value for the catch block. + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. # - # Modifies expectation so that when the expected method is called, it throws the specified +tag+ with the specific return value +object+ i.e. calls Kernel#throw(tag, object). + # @see Kernel#throw + # @see #then + # + # @overload def throw(tag) + # @overload def throw(tag, object) + # + # @example Throw tag when expected method is invoked. # object = stub() # object.stubs(:expected_method).throws(:done) # object.expected_method # => throws tag :done - # Note you can also pass in an optional return value +object+ (just as you can for Kernel#throw). + # + # @example Throw tag with return value +object+ c.f. +Kernel#throw+. # object = stub() # object.stubs(:expected_method).throws(:done, 'result') # object.expected_method # => throws tag :done and causes catch block to return 'result' - # May be called multiple times on the same expectation. Also see Expectation#then. + # + # @example Throw different tags on consecutive invocations of the expected method. # object = stub() # object.stubs(:expected_method).throws(:done).then.throws(:continue) # object.expected_method # => throws :done # object.expected_method # => throws :continue - # May be called in conjunction with Expectation#returns on the same expectation. + # + # @example Throw tag on first invocation of expected method and then return values for subsequent invocations. # object = stub() # object.stubs(:expected_method).throws(:done).then.returns(2, 3) # object.expected_method # => throws :done @@ -340,10 +407,19 @@ def throws(tag, object = nil) self end - # :call-seq: then() -> expectation - # then(state_machine.is(state)) -> expectation + # @overload def then + # Used as syntactic sugar to improve readability. It has no effect on state of the expectation. + # @overload def then(state_machine.is(state_name)) + # Used to change the +state_machine+ to the state specified by +state_name+ when the expected invocation occurs. + # @param [StateMachine::State] state_machine.is(state_name) provides a mechanism to change the +state_machine+ into the state specified by +state_name+ when the expected method is invoked. + # + # @see API#states + # @see StateMachine + # @see #when + # + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. # - # then() is used as syntactic sugar to improve readability. It has no effect on state of the expectation. + # @example Using {#then} as syntactic sugar when specifying values to be returned and exceptions to be raised on consecutive invocations of the expected method. # object = mock() # object.stubs(:expected_method).returns(1, 2).then.raises(Exception).then.returns(4) # object.expected_method # => 1 @@ -351,9 +427,7 @@ def throws(tag, object = nil) # object.expected_method # => raises exception of class Exception # object.expected_method # => 4 # - # then(state_machine.is(state)) is used to change the +state_machine+ to the specified +state+ when the invocation occurs. - # - # See also API#states, StateMachine and Expectation#when. + # @example Using {#then} to change the +state+ of a +state_machine+ on the invocation of an expected method. # power = states('power').starts_as('off') # # radio = mock('radio') @@ -371,11 +445,16 @@ def then(*parameters) self end - # :call-seq: when(state_machine.is(state)) -> exception + # Constrains the expectation to occur only when the +state_machine+ is in the state specified by +state_name+. + # + # @param [StateMachine::StatePredicate] state_machine.is(state_name) provides a mechanism to determine whether the +state_machine+ is in the state specified by +state_name+ when the expected method is invoked. + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. # - # Constrains the expectation to occur only when the +state_machine+ is in the named +state+. + # @see API#states + # @see StateMachine + # @see #then # - # See also API#states, StateMachine#starts_as and Expectation#then. + # @example Using {#when} to only allow invocation of methods when "power" state machine is in the "on" state. # power = states('power').starts_as('off') # # radio = mock('radio') @@ -390,17 +469,22 @@ def when(state_predicate) self end - # :call-seq: in_sequence(*sequences) -> expectation + # Constrains the expectation so that it must be invoked at the current point in the +sequence+. # - # Constrains this expectation so that it must be invoked at the current point in the sequence. + # To expect a sequence of invocations, write the expectations in order and add the +in_sequence(sequence)+ clause to each one. # - # To expect a sequence of invocations, write the expectations in order and add the in_sequence(sequence) clause to each one. + # Expectations in a +sequence+ can have any invocation count. # - # Expectations in a sequence can have any invocation count. + # If an expectation in a sequence is stubbed, rather than expected, it can be skipped in the +sequence+. # - # If an expectation in a sequence is stubbed, rather than expected, it can be skipped in the sequence. + # An expected method can appear in multiple sequences. # - # See also API#sequence. + # @param [*Array] sequences sequences in which expected method should appear. + # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained. + # + # @see API#sequence + # + # @example Ensure methods are invoked in a specified order. # breakfast = sequence('breakfast') # # egg = mock('egg') @@ -412,10 +496,10 @@ def in_sequence(*sequences) self end - # :stopdoc: - + # @private attr_reader :backtrace + # @private def initialize(mock, expected_method_name, backtrace = nil) @mock = mock @method_matcher = MethodMatcher.new(expected_method_name.to_sym) @@ -428,42 +512,52 @@ def initialize(mock, expected_method_name, backtrace = nil) @backtrace = backtrace || caller end + # @private def add_ordering_constraint(ordering_constraint) @ordering_constraints << ordering_constraint end + # @private def add_in_sequence_ordering_constraint(sequence) sequence.constrain_as_next_in_sequence(self) end + # @private def add_side_effect(side_effect) @side_effects << side_effect end + # @private def perform_side_effects @side_effects.each { |side_effect| side_effect.perform } end + # @private def in_correct_order? @ordering_constraints.all? { |ordering_constraint| ordering_constraint.allows_invocation_now? } end + # @private def matches_method?(method_name) @method_matcher.match?(method_name) end + # @private def match?(actual_method_name, *actual_parameters) @method_matcher.match?(actual_method_name) && @parameters_matcher.match?(actual_parameters) && in_correct_order? end + # @private def invocations_allowed? @cardinality.invocations_allowed?(@invocation_count) end + # @private def satisfied? @cardinality.satisfied?(@invocation_count) end + # @private def invoke @invocation_count += 1 perform_side_effects() @@ -475,15 +569,18 @@ def invoke @return_values.next end + # @private def verified?(assertion_counter = nil) assertion_counter.increment if assertion_counter && @cardinality.needs_verifying? @cardinality.verified?(@invocation_count) end + # @private def used? @cardinality.used?(@invocation_count) end + # @private def mocha_inspect message = "#{@cardinality.mocha_inspect}, " message << case @invocation_count @@ -498,12 +595,11 @@ def mocha_inspect message end + # @private def method_signature "#{@mock.mocha_inspect}.#{@method_matcher.mocha_inspect}#{@parameters_matcher.mocha_inspect}" end - # :startdoc: - end end diff --git a/lib/mocha/mock.rb b/lib/mocha/mock.rb index 9660f3e17..faf2b769f 100644 --- a/lib/mocha/mock.rb +++ b/lib/mocha/mock.rb @@ -7,37 +7,47 @@ require 'mocha/unexpected_invocation' require 'mocha/argument_iterator' -module Mocha # :nodoc: +module Mocha # Traditional mock object. # - # Methods return an Expectation which can be further modified by methods on Expectation. + # All methods return an {Expectation} which can be further modified by methods on {Expectation}. class Mock - # :call-seq: expects(method_name) -> expectation - # expects(method_names_vs_return_values) -> last expectation + # Adds an expectation that the specified method must be called exactly once with any parameters. # - # Adds an expectation that a method identified by +method_name+ Symbol/String must be called exactly once with any parameters. - # Returns the new expectation which can be further modified by methods on Expectation. - # object = mock() - # object.expects(:method1) - # object.method1 - # # no error raised + # @param [Symbol,String] method_name name of expected method + # @param [Hash] expected_methods_vs_return_values expected method name symbols as keys and corresponding return values as values - these expectations are setup as if {#expects} were called multiple times. # + # @overload def expects(method_name) + # @overload def expects(expected_methods_vs_return_values) + # @return [Expectation] last-built expectation which can be further modified by methods on {Expectation}. + # + # @example Expected method invoked once so no error raised # object = mock() - # object.expects(:method1) - # # error raised, because method1 not called exactly once - # If +method_names_vs_return_values+ is a +Hash+, an expectation will be set up for each entry using the key as +method_name+ and value as +return_value+. + # object.expects(:expected_method) + # object.expected_method + # + # @example Expected method not invoked so error raised # object = mock() - # object.expects(:method1 => :result1, :method2 => :result2) + # object.expects(:expected_method) + # # error raised when test completes, because expected_method not called exactly once # - # # exactly equivalent to + # @example Expected method invoked twice so error raised + # object = mock() + # object.expects(:expected_method) + # object.expected_method + # object.expected_method # => error raised when expected method invoked second time # + # @example Setup multiple expectations using +expected_methods_vs_return_values+. # object = mock() - # object.expects(:method1).returns(:result1) - # object.expects(:method2).returns(:result2) + # object.expects(:expected_method_one => :result_one, :expected_method_two => :result_two) + # + # # is exactly equivalent to # - # Aliased by \_\_expects\_\_ + # object = mock() + # object.expects(:expected_method_one).returns(:result_one) + # object.expects(:expected_method_two).returns(:result_two) def expects(method_name_or_hash, backtrace = nil) iterator = ArgumentIterator.new(method_name_or_hash) iterator.each { |*args| @@ -49,27 +59,31 @@ def expects(method_name_or_hash, backtrace = nil) } end - # :call-seq: stubs(method_name) -> expectation - # stubs(method_names_vs_return_values) -> last expectation + # Adds an expectation that the specified method may be called any number of times with any parameters. # - # Adds an expectation that a method identified by +method_name+ Symbol/String may be called any number of times with any parameters. - # Returns the new expectation which can be further modified by methods on Expectation. + # @param [Symbol,String] method_name name of stubbed method + # @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {#stubs} were called multiple times. + # + # @overload def stubs(method_name) + # @overload def stubs(stubbed_methods_vs_return_values) + # @return [Expectation] last-built expectation which can be further modified by methods on {Expectation}. + # + # @example No error raised however many times stubbed method is invoked # object = mock() - # object.stubs(:method1) - # object.method1 - # object.method1 + # object.stubs(:stubbed_method) + # object.stubbed_method + # object.stubbed_method # # no error raised - # If +method_names_vs_return_values+ is a +Hash+, an expectation will be set up for each entry using the key as +method_name+ and value as +return_value+. + # + # @example Setup multiple expectations using +stubbed_methods_vs_return_values+. # object = mock() - # object.stubs(:method1 => :result1, :method2 => :result2) + # object.stubs(:stubbed_method_one => :result_one, :stubbed_method_two => :result_two) # - # # exactly equivalent to + # # is exactly equivalent to # # object = mock() - # object.stubs(:method1).returns(:result1) - # object.stubs(:method2).returns(:result2) - # - # Aliased by \_\_stubs\_\_ + # object.stubs(:stubbed_method_one).returns(:result_one) + # object.stubs(:stubbed_method_two).returns(:result_two) def stubs(method_name_or_hash, backtrace = nil) iterator = ArgumentIterator.new(method_name_or_hash) iterator.each { |*args| @@ -82,30 +96,30 @@ def stubs(method_name_or_hash, backtrace = nil) } end - # :call-seq: unstub(method_name) + # Removes the specified stubbed method (added by calls to {#expects} or {#stubs}) and all expectations associated with it. # - # Removes all expectations for method identified by +method_name+. - # object = mock('mock') - # object.stubs(:method1).returns(:result1) - # object.method1 # => :result1 - # object.unstub(:method1) - # object.method1 # => unexpected invocation: #.method1() + # @param [Symbol] method_name name of method to unstub. + # + # @example Invoking an unstubbed method causes error to be raised + # object = mock('mock') do + # object.stubs(:stubbed_method).returns(:result_one) + # object.stubbed_method # => :result_one + # object.unstub(:stubbed_method) + # object.stubbed_method # => unexpected invocation: #.stubbed_method() def unstub(method_name) @expectations.remove_all_matching_method(method_name) end - # :call-seq: responds_like(responder) -> mock + # Constrains the {Mock} instance so that it can only expect or stub methods to which +responder+ responds. The constraint is only applied at method invocation time. # - # Constrains the +mock+ so that it can only expect or stub methods to which +responder+ responds. The constraint is only applied at method invocation time. + # A +NoMethodError+ will be raised if the +responder+ does not +#respond_to?+ a method invocation (even if the method has been expected or stubbed). # - # A +NoMethodError+ will be raised if the +responder+ does not respond_to? a method invocation (even if the method has been expected or stubbed). + # The {Mock} instance will delegate its +#respond_to?+ method to the +responder+. # - # The +mock+ will delegate its respond_to? method to the +responder+. - # class Sheep - # def chew(grass); end - # def self.number_of_legs; end - # end + # @param [Object, #respond_to?] responder an object used to determine whether {Mock} instance should +#respond_to?+ to an invocation. + # @return [Mock] the same {Mock} instance, thereby allowing invocations of other {Mock} methods to be chained. # + # @example Normal mocking # sheep = mock('sheep') # sheep.expects(:chew) # sheep.expects(:foo) @@ -115,6 +129,11 @@ def unstub(method_name) # sheep.foo # # no error raised # + # @example Using {#responds_like} with an instance method + # class Sheep + # def chew(grass); end + # end + # # sheep = mock('sheep') # sheep.responds_like(Sheep.new) # sheep.expects(:chew) @@ -124,6 +143,11 @@ def unstub(method_name) # sheep.chew # sheep.foo # => raises NoMethodError exception # + # @example Using {#responds_like} with a class method + # class Sheep + # def self.number_of_legs; end + # end + # # sheep_class = mock('sheep_class') # sheep_class.responds_like(Sheep) # sheep_class.stubs(:number_of_legs).returns(4) @@ -132,15 +156,12 @@ def unstub(method_name) # sheep_class.respond_to?(:foo) # => false # assert_equal 4, sheep_class.number_of_legs # sheep_class.foo # => raises NoMethodError exception - # - # Aliased by +quacks_like+ - def responds_like(object) - @responder = object + def responds_like(responder) + @responder = responder self end - # :stopdoc: - + # @private def initialize(mockery, name = nil, &block) @mockery = mockery @name = name || DefaultName.new(self) @@ -150,6 +171,7 @@ def initialize(mockery, name = nil, &block) instance_eval(&block) if block end + # @private attr_reader :everything_stubbed alias_method :__expects__, :expects @@ -158,14 +180,17 @@ def initialize(mockery, name = nil, &block) alias_method :quacks_like, :responds_like + # @private def __expectations__ @expectations end + # @private def stub_everything @everything_stubbed = true end + # @private def method_missing(symbol, *arguments, &block) if @responder and not @responder.respond_to?(symbol) raise NoMethodError, "undefined method `#{symbol}' for #{self.mocha_inspect} which responds like #{@responder.mocha_inspect}" @@ -182,6 +207,7 @@ def method_missing(symbol, *arguments, &block) end end + # @private def respond_to?(symbol, include_private = false) if @responder then if @responder.method(:respond_to?).arity > 1 @@ -194,28 +220,31 @@ def respond_to?(symbol, include_private = false) end end + # @private def __verified__?(assertion_counter = nil) @expectations.verified?(assertion_counter) end + # @private def mocha_inspect @name.mocha_inspect end + # @private def inspect mocha_inspect end + # @private def ensure_method_not_already_defined(method_name) self.__metaclass__.send(:undef_method, method_name) if self.__metaclass__.method_defined?(method_name) end + # @private def any_expectations? @expectations.any? end - # :startdoc: - end end diff --git a/lib/mocha/object.rb b/lib/mocha/object.rb index 4042d6240..eaabb217c 100644 --- a/lib/mocha/object.rb +++ b/lib/mocha/object.rb @@ -6,42 +6,49 @@ require 'mocha/argument_iterator' module Mocha - - # Methods added to all objects to allow mocking and stubbing on real objects. + + # Methods added to all objects to allow mocking and stubbing on real (i.e. non-mock) objects. # - # Methods return a Mocha::Expectation which can be further modified by methods on Mocha::Expectation. + # Both {#expects} and {#stubs} return an {Expectation} which can be further modified by methods on {Expectation}. module ObjectMethods - - def mocha # :nodoc: + + # @private + def mocha @mocha ||= Mocha::Mockery.instance.mock_impersonating(self) end - - def reset_mocha # :nodoc: + + # @private + def reset_mocha @mocha = nil end - - def stubba_method # :nodoc: + + # @private + def stubba_method Mocha::InstanceMethod end - - def stubba_object # :nodoc: + + # @private + def stubba_object self end - - # :call-seq: expects(method_name) -> expectation - # expects(method_names_vs_return_values) -> last expectation + + # Adds an expectation that the specified method must be called exactly once with any parameters. + # + # The original implementation of the method is replaced during the test and then restored at the end of the test. + # + # @param [Symbol,String] method_name name of expected method + # @param [Hash] expected_methods_vs_return_values expected method name symbols as keys and corresponding return values as values - these expectations are setup as if {#expects} were called multiple times. # - # Adds an expectation that a method identified by +method_name+ Symbol must be called exactly once with any parameters. - # Returns the new expectation which can be further modified by methods on Mocha::Expectation. + # @overload def expects(method_name) + # @overload def expects(expected_methods_vs_return_values) + # @return [Expectation] last-built expectation which can be further modified by methods on {Expectation}. + # + # @example Setting up an expectation on a non-mock object. # product = Product.new # product.expects(:save).returns(true) # assert_equal true, product.save # - # The original implementation of Product#save is replaced temporarily. - # - # The original implementation of Product#save is restored at the end of the test. - # - # If +method_names_vs_return_values+ is a +Hash+, an expectation will be set up for each entry using the key as +method_name+ and value as +return_value+. + # @example Setting up multiple expectations on a non-mock object. # product = Product.new # product.expects(:valid? => true, :save => true) # @@ -50,13 +57,15 @@ def stubba_object # :nodoc: # product = Product.new # product.expects(:valid?).returns(true) # product.expects(:save).returns(true) - def expects(method_name_or_hash) - if method_name_or_hash.to_s =~ /the[^a-z]*spanish[^a-z]*inquisition/i + # + # @see Mock#expects + def expects(expected_methods_vs_return_values) + if expected_methods_vs_return_values.to_s =~ /the[^a-z]*spanish[^a-z]*inquisition/i raise Mocha::ExpectationError.new('NOBODY EXPECTS THE SPANISH INQUISITION!') end expectation = nil mockery = Mocha::Mockery.instance - iterator = ArgumentIterator.new(method_name_or_hash) + iterator = ArgumentIterator.new(expected_methods_vs_return_values) iterator.each { |*args| method_name = args.shift mockery.on_stubbing(self, method_name) @@ -67,21 +76,22 @@ def expects(method_name_or_hash) } expectation end - - # :call-seq: stubs(method_name) -> expectation - # stubs(method_names_vs_return_values) -> last expectation + + # Adds an expectation that the specified method may be called any number of times with any parameters. # - # Adds an expectation that a method identified by +method_name+ Symbol may be called any number of times with any parameters. - # Returns the new expectation which can be further modified by methods on Mocha::Expectation. + # @param [Symbol,String] method_name name of stubbed method + # @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {#stubs} were called multiple times. + # + # @overload def stubs(method_name) + # @overload def stubs(stubbed_methods_vs_return_values) + # @return [Expectation] last-built expectation which can be further modified by methods on {Expectation}. + # + # @example Setting up a stubbed methods on a non-mock object. # product = Product.new # product.stubs(:save).returns(true) # assert_equal true, product.save # - # The original implementation of Product#save is replaced temporarily. - # - # The original implementation of Product#save is restored at the end of the test. - # - # If +method_names_vs_return_values+ is a +Hash+, an expectation will be set up for each entry using the key as +method_name+ and value as +return_value+. + # @example Setting up multiple stubbed methods on a non-mock object. # product = Product.new # product.stubs(:valid? => true, :save => true) # @@ -90,10 +100,12 @@ def expects(method_name_or_hash) # product = Product.new # product.stubs(:valid?).returns(true) # product.stubs(:save).returns(true) - def stubs(method_name_or_hash) + # + # @see Mock#stubs + def stubs(stubbed_methods_vs_return_values) expectation = nil mockery = Mocha::Mockery.instance - iterator = ArgumentIterator.new(method_name_or_hash) + iterator = ArgumentIterator.new(stubbed_methods_vs_return_values) iterator.each { |*args| method_name = args.shift mockery.on_stubbing(self, method_name) @@ -104,26 +116,24 @@ def stubs(method_name_or_hash) } expectation end - - # :call-seq: unstub(*method_names) + + # Removes the specified stubbed methods (added by calls to {#expects} or {#stubs}) and all expectations associated with them. + # + # Restores the original behaviour of the methods before they were stubbed. + # + # WARNING: If you {#unstub} a method which still has unsatisfied expectations, you may be removing the only way those expectations can be satisfied. Use {#unstub} with care. # - # Removes the method stub added by calls to #expects or #stubs. - # Restores the original behaviour of the method before it was stubbed. + # @param [Array] method_names names of methods to unstub. + # + # @example Stubbing and unstubbing a method on a real (non-mock) object. # multiplier = Multiplier.new # multiplier.double(2) # => 4 - # multiplier.stubs(:double).raises + # multiplier.stubs(:double).raises # new behaviour defined # multiplier.double(2) # => raises exception - # multiplier.unstub(:double) + # multiplier.unstub(:double) # original behaviour restored # multiplier.double(2) # => 4 # - # The original implementation of Multiplier#double is replaced temporarily. - # - # The original implementation of Multiplier#double is restored when #unstub is called. - # - # WARNING: If you #unstub a method which still has unsatisfied expectations, you may be removing - # the only way those expectations can be satisfied. Use #unstub with care. - # - # If multiple +method_names+ are supplied, each method is unstubbed. + # @example Unstubbing multiple methods on a real (non-mock) object. # multiplier.unstub(:double, :triple) # # # exactly equivalent to @@ -137,8 +147,9 @@ def unstub(*method_names) mockery.stubba.unstub(method) end end - - def method_exists?(method, include_public_methods = true) # :nodoc: + + # @private + def method_exists?(method, include_public_methods = true) if include_public_methods return true if public_methods(include_superclass_methods = true).include?(method) return true if respond_to?(method.to_sym) @@ -147,30 +158,33 @@ def method_exists?(method, include_public_methods = true) # :nodoc: return true if private_methods(include_superclass_methods = true).include?(method) return false end - + end - - module ModuleMethods # :nodoc: - + + # @private + module ModuleMethods + def stubba_method Mocha::ModuleMethod end - + end - - # Methods added all classes to allow mocking and stubbing on real objects. + + # Methods added to all classes to allow mocking and stubbing on real (i.e. non-mock) objects. module ClassMethods - - def stubba_method # :nodoc: + + # @private + def stubba_method Mocha::ClassMethod end - class AnyInstance # :nodoc: - + # @private + class AnyInstance + def initialize(klass) @stubba_object = klass end - + def mocha @mocha ||= Mocha::Mockery.instance.mock_impersonating_any_instance_of(@stubba_object) end @@ -178,11 +192,11 @@ def mocha def stubba_method Mocha::AnyInstanceMethod end - + def stubba_object @stubba_object end - + def method_exists?(method, include_public_methods = true) if include_public_methods return true if @stubba_object.public_instance_methods(include_superclass_methods = true).include?(method) @@ -191,12 +205,12 @@ def method_exists?(method, include_public_methods = true) return true if @stubba_object.private_instance_methods(include_superclass_methods = true).include?(method) return false end - + end - - # :call-seq: any_instance -> mock object + + # @return [Mock] a mock object which will detect calls to any instance of this class. # - # Returns a mock object which will detect calls to any instance of this class. + # @example Return false to invocation of +Product#save+ for any instance of +Product+. # Product.any_instance.stubs(:save).returns(false) # product_1 = Product.new # assert_equal false, product_1.save @@ -205,19 +219,22 @@ def method_exists?(method, include_public_methods = true) def any_instance @any_instance ||= AnyInstance.new(self) end - + end - + end -class Object # :nodoc: +# @private +class Object include Mocha::ObjectMethods end -class Module # :nodoc: +# @private +class Module include Mocha::ModuleMethods end -class Class # :nodoc: +# @private +class Class include Mocha::ClassMethods end diff --git a/lib/mocha/parameter_matchers.rb b/lib/mocha/parameter_matchers.rb index 47c23bcf9..460556e07 100644 --- a/lib/mocha/parameter_matchers.rb +++ b/lib/mocha/parameter_matchers.rb @@ -1,8 +1,8 @@ module Mocha - - # Used as parameters for Expectation#with to restrict the parameter values which will match the expectation. Can be nested. + + # Used as parameters for {Expectation#with} to restrict the parameter values which will match the expectation. Can be nested. module ParameterMatchers; end - + end require 'mocha/parameter_matchers/object' diff --git a/lib/mocha/parameter_matchers/all_of.rb b/lib/mocha/parameter_matchers/all_of.rb index 50bf05b62..eb1ebbde2 100644 --- a/lib/mocha/parameter_matchers/all_of.rb +++ b/lib/mocha/parameter_matchers/all_of.rb @@ -1,17 +1,23 @@ require 'mocha/parameter_matchers/base' module Mocha - + module ParameterMatchers - # :call-seq: all_of(*parameter_matchers) -> parameter_matcher + # Matches if all +matchers+ match. + # + # @param [*Array] parameter_matchers parameter matchers. + # @return [AllOf] parameter matcher. + # + # @see Expectation#with # - # Matches if all +parameter_matchers+ match. + # @example All parameter matchers match. # object = mock() # object.expects(:method_1).with(all_of(includes(1), includes(3))) # object.method_1([1, 3]) # # no error raised # + # @example One of the parameter matchers does not match. # object = mock() # object.expects(:method_1).with(all_of(includes(1), includes(3))) # object.method_1([1, 2]) @@ -19,24 +25,28 @@ module ParameterMatchers def all_of(*matchers) AllOf.new(*matchers) end - - class AllOf < Base # :nodoc: - + + # Parameter matcher which combines a number of other matchers using a logical AND. + class AllOf < Base + + # @private def initialize(*matchers) @matchers = matchers end - + + # @private def matches?(available_parameters) parameter = available_parameters.shift @matchers.all? { |matcher| matcher.to_matcher.matches?([parameter]) } end - + + # @private def mocha_inspect "all_of(#{@matchers.map { |matcher| matcher.mocha_inspect }.join(", ") })" end - + end - + end - -end \ No newline at end of file + +end diff --git a/lib/mocha/parameter_matchers/any_of.rb b/lib/mocha/parameter_matchers/any_of.rb index b391ff33a..cd051d8b2 100644 --- a/lib/mocha/parameter_matchers/any_of.rb +++ b/lib/mocha/parameter_matchers/any_of.rb @@ -1,22 +1,29 @@ require 'mocha/parameter_matchers/base' module Mocha - + module ParameterMatchers - # :call-seq: any_of(*parameter_matchers) -> parameter_matcher + # Matches if any +matchers+ match. + # + # @param [*Array] parameter_matchers parameter matchers. + # @return [AnyOf] parameter matcher. + # + # @see Expectation#with # - # Matches if any +parameter_matchers+ match. + # @example One parameter matcher matches. # object = mock() # object.expects(:method_1).with(any_of(1, 3)) # object.method_1(1) # # no error raised # + # @example The other parameter matcher matches. # object = mock() # object.expects(:method_1).with(any_of(1, 3)) # object.method_1(3) # # no error raised # + # @example Neither parameter matcher matches. # object = mock() # object.expects(:method_1).with(any_of(1, 3)) # object.method_1(2) @@ -24,24 +31,28 @@ module ParameterMatchers def any_of(*matchers) AnyOf.new(*matchers) end - - class AnyOf < Base # :nodoc: - + + # Parameter matcher which combines a number of other matchers using a logical OR. + class AnyOf < Base + + # @private def initialize(*matchers) @matchers = matchers end - + + # @private def matches?(available_parameters) parameter = available_parameters.shift @matchers.any? { |matcher| matcher.to_matcher.matches?([parameter]) } end - + + # @private def mocha_inspect "any_of(#{@matchers.map { |matcher| matcher.mocha_inspect }.join(", ") })" end - + end - + end - -end \ No newline at end of file + +end diff --git a/lib/mocha/parameter_matchers/any_parameters.rb b/lib/mocha/parameter_matchers/any_parameters.rb index 11dae83ed..0c90d166c 100644 --- a/lib/mocha/parameter_matchers/any_parameters.rb +++ b/lib/mocha/parameter_matchers/any_parameters.rb @@ -1,12 +1,16 @@ require 'mocha/parameter_matchers/base' module Mocha - + module ParameterMatchers - # :call-seq: any_parameters() -> parameter_matcher + # Matches any parameters. This is used as the default for a newly built expectation. + # + # @return [AnyParameters] parameter matcher. + # + # @see Expectation#with # - # Matches any parameters. + # @example Any parameters will match. # object = mock() # object.expects(:method_1).with(any_parameters) # object.method_1(1, 2, 3, 4) @@ -20,8 +24,10 @@ def any_parameters AnyParameters.new end - class AnyParameters < Base # :nodoc: - + # Parameter matcher which always matches whatever the parameters. + class AnyParameters < Base + + # @private def matches?(available_parameters) while available_parameters.length > 0 do available_parameters.shift @@ -29,12 +35,13 @@ def matches?(available_parameters) return true end + # @private def mocha_inspect "any_parameters" end end - + end - -end \ No newline at end of file + +end diff --git a/lib/mocha/parameter_matchers/anything.rb b/lib/mocha/parameter_matchers/anything.rb index 90510e269..11b9ab3eb 100644 --- a/lib/mocha/parameter_matchers/anything.rb +++ b/lib/mocha/parameter_matchers/anything.rb @@ -1,33 +1,42 @@ require 'mocha/parameter_matchers/base' module Mocha - + module ParameterMatchers - # :call-seq: anything() -> parameter_matcher - # # Matches any object. + # + # @return [Anything] parameter matcher. + # + # @see Expectation#with + # + # @example Any object will match. # object = mock() # object.expects(:method_1).with(anything) # object.method_1('foo') + # object.method_1(789) + # object.method_1(:bar) # # no error raised def anything Anything.new end - - class Anything < Base # :nodoc: - + + # Parameter matcher which always matches a single parameter. + class Anything < Base + + # @private def matches?(available_parameters) available_parameters.shift return true end - + + # @private def mocha_inspect "anything" end - + end - + end - -end \ No newline at end of file + +end diff --git a/lib/mocha/parameter_matchers/base.rb b/lib/mocha/parameter_matchers/base.rb index 099f0df68..2eff5f8de 100644 --- a/lib/mocha/parameter_matchers/base.rb +++ b/lib/mocha/parameter_matchers/base.rb @@ -1,53 +1,61 @@ module Mocha - + module ParameterMatchers - + + # @abstract Subclass and implement +#matches?+ and +#mocha_inspect+ to define a custom matcher. Also add a suitably named instance method to {ParameterMatchers} to build an instance of the new matcher c.f. {#equals}. class Base - - def to_matcher # :nodoc: + + # @private + def to_matcher self end - - # :call-seq: &(matcher) -> parameter_matcher + + # A shorthand way of combining two matchers when both must match. # - # A short hand way of specifying multiple matchers that should - # all match. + # Returns a new {AllOf} parameter matcher combining two matchers using a logical AND. # - # Returns a new +AllOf+ parameter matcher combining the - # given matcher and the receiver. + # This shorthand will not work with an implicit equals match. Instead, an explicit {Equals} matcher should be used. # - # The following statements are equivalent: + # @param [Base] matcher parameter matcher. + # @return [AllOf] parameter matcher. + # + # @see Expectation#with + # + # @example Alternative ways to combine matchers with a logical AND. # object = mock() # object.expects(:run).with(all_of(has_key(:foo), has_key(:bar))) # object.run(:foo => 'foovalue', :bar => 'barvalue') # - # # with the shorthand + # # is exactly equivalent to + # # object.expects(:run).with(has_key(:foo) & has_key(:bar)) # object.run(:foo => 'foovalue', :bar => 'barvalue) def &(matcher) AllOf.new(self, matcher) end - - # :call-seq: |(matcher) -> parameter_matcher + + # A shorthand way of combining two matchers when at least one must match. + # + # Returns a new +AnyOf+ parameter matcher combining two matchers using a logical OR. # - # A short hand way of specifying multiple matchers, only at least - # one of which should pass. + # This shorthand will not work with an implicit equals match. Instead, an explicit {Equals} matcher should be used. # - # Returns a new +AnyOf+ parameter matcher combining the - # given matcher and the receiver. + # @param [Base] matcher parameter matcher. + # @return [AnyOf] parameter matcher. # - # The following statements are equivalent: + # @see Expectation#with + # + # @example Alternative ways to combine matchers with a logical OR. # object = mock() # object.expects(:run).with(any_of(has_key(:foo), has_key(:bar))) # object.run(:foo => 'foovalue') # - # # with the shorthand + # # is exactly equivalent to + # # object.expects(:run).with(has_key(:foo) | has_key(:bar)) # object.run(:foo => 'foovalue') # - # This shorthand will not work with an implicit equals match. Instead, - # an explicit equals matcher should be used: - # + # @example Using an explicit {Equals} matcher in combination with {#|}. # object.expects(:run).with(equals(1) | equals(2)) # object.run(1) # passes # object.run(2) # passes @@ -55,9 +63,9 @@ def &(matcher) def |(matcher) AnyOf.new(self, matcher) end - + end - + end - + end diff --git a/lib/mocha/parameter_matchers/equals.rb b/lib/mocha/parameter_matchers/equals.rb index bdc61a0f5..e82271817 100644 --- a/lib/mocha/parameter_matchers/equals.rb +++ b/lib/mocha/parameter_matchers/equals.rb @@ -1,42 +1,53 @@ require 'mocha/parameter_matchers/base' module Mocha - + module ParameterMatchers - # :call-seq: equals(value) -> parameter_matcher + # Matches any +Object+ equalling +value+. + # + # @param [Object] value expected value. + # @return [Equals] parameter matcher. + # + # @see Expectation#with + # @see Object#== # - # Matches +Object+ equalling +value+. + # @example Actual parameter equals expected parameter. # object = mock() # object.expects(:method_1).with(equals(2)) # object.method_1(2) # # no error raised # + # @example Actual parameter does not equal expected parameter. # object = mock() # object.expects(:method_1).with(equals(2)) # object.method_1(3) - # # error raised, because method_1 was not called with Object equalling 3 + # # error raised, because method_1 was not called with an +Object+ that equals 3 def equals(value) Equals.new(value) end - class Equals < Base # :nodoc: - + # Parameter matcher which matches when actual parameter equals expected value. + class Equals < Base + + # @private def initialize(value) @value = value end - + + # @private def matches?(available_parameters) parameter = available_parameters.shift parameter == @value end - + + # @private def mocha_inspect @value.mocha_inspect end - + end - + end - -end \ No newline at end of file + +end diff --git a/lib/mocha/parameter_matchers/has_entries.rb b/lib/mocha/parameter_matchers/has_entries.rb index 03e968f86..a21730176 100644 --- a/lib/mocha/parameter_matchers/has_entries.rb +++ b/lib/mocha/parameter_matchers/has_entries.rb @@ -3,17 +3,23 @@ require 'mocha/parameter_matchers/has_entry' module Mocha - + module ParameterMatchers - # :call-seq: has_entries(entries) -> parameter_matcher - # # Matches +Hash+ containing all +entries+. + # + # @param [Hash] entries expected +Hash+ entries. + # @return [HasEntries] parameter matcher. + # + # @see Expectation#with + # + # @example Actual parameter contains all expected entries. # object = mock() # object.expects(:method_1).with(has_entries('key_1' => 1, 'key_2' => 2)) # object.method_1('key_1' => 1, 'key_2' => 2, 'key_3' => 3) # # no error raised # + # @example Actual parameter does not contain all expected entries. # object = mock() # object.expects(:method_1).with(has_entries('key_1' => 1, 'key_2' => 2)) # object.method_1('key_1' => 1, 'key_2' => 99) @@ -21,25 +27,29 @@ module ParameterMatchers def has_entries(entries) HasEntries.new(entries) end - - class HasEntries < Base # :nodoc: - + + # Parameter matcher which matches when actual parameter contains all expected +Hash+ entries. + class HasEntries < Base + + # @private def initialize(entries) @entries = entries end - + + # @private def matches?(available_parameters) parameter = available_parameters.shift has_entry_matchers = @entries.map { |key, value| HasEntry.new(key, value) } AllOf.new(*has_entry_matchers).matches?([parameter]) end - + + # @private def mocha_inspect "has_entries(#{@entries.mocha_inspect})" end - + end - + end - -end \ No newline at end of file + +end diff --git a/lib/mocha/parameter_matchers/has_entry.rb b/lib/mocha/parameter_matchers/has_entry.rb index 85d250545..1a03a0f2e 100644 --- a/lib/mocha/parameter_matchers/has_entry.rb +++ b/lib/mocha/parameter_matchers/has_entry.rb @@ -1,28 +1,42 @@ require 'mocha/parameter_matchers/base' module Mocha - + module ParameterMatchers - # :call-seq: has_entry(key, value) -> parameter_matcher - # has_entry(key => value) -> parameter_matcher - # # Matches +Hash+ containing entry with +key+ and +value+. + # + # @overload def has_entry(key, value) + # @param [Object] key key for entry. + # @param [Object] value value for entry. + # @overload def has_entry(single_entry_hash) + # @param [Hash] single_entry_hash +Hash+ with single entry. + # @raise [ArgumentError] if +single_entry_hash+ does not contain exactly one entry. + # + # @return [HasEntry] parameter matcher. + # + # @see Expectation#with + # + # @example Actual parameter contains expected entry supplied as key and value. # object = mock() # object.expects(:method_1).with(has_entry('key_1', 1)) # object.method_1('key_1' => 1, 'key_2' => 2) # # no error raised # + # @example Actual parameter contains expected entry supplied as +Hash+ entry. # object = mock() # object.expects(:method_1).with(has_entry('key_1' => 1)) # object.method_1('key_1' => 1, 'key_2' => 2) # # no error raised # + # @example Actual parameter does not contain expected entry supplied as key and value. # object = mock() # object.expects(:method_1).with(has_entry('key_1', 1)) # object.method_1('key_1' => 2, 'key_2' => 1) # # error raised, because method_1 was not called with Hash containing entry: 'key_1' => 1 # + # @example Actual parameter does not contain expected entry supplied as +Hash+ entry. + # # object = mock() # object.expects(:method_1).with(has_entry('key_1' => 1)) # object.method_1('key_1' => 2, 'key_2' => 1) @@ -41,26 +55,30 @@ def has_entry(*options) end HasEntry.new(key, value) end - - class HasEntry < Base # :nodoc: - + + # Parameter matcher which matches when actual parameter contains expected +Hash+ entry. + class HasEntry < Base + + # @private def initialize(key, value) @key, @value = key, value end - + + # @private def matches?(available_parameters) parameter = available_parameters.shift return false unless parameter.respond_to?(:keys) && parameter.respond_to?(:[]) matching_keys = parameter.keys.select { |key| @key.to_matcher.matches?([key]) } matching_keys.any? { |key| @value.to_matcher.matches?([parameter[key]]) } end - + + # @private def mocha_inspect "has_entry(#{@key.mocha_inspect} => #{@value.mocha_inspect})" end - + end - + end - -end \ No newline at end of file + +end diff --git a/lib/mocha/parameter_matchers/has_key.rb b/lib/mocha/parameter_matchers/has_key.rb index 23fffb966..9f5441662 100644 --- a/lib/mocha/parameter_matchers/has_key.rb +++ b/lib/mocha/parameter_matchers/has_key.rb @@ -1,17 +1,23 @@ require 'mocha/parameter_matchers/base' module Mocha - + module ParameterMatchers - # :call-seq: has_key(key) -> parameter_matcher - # # Matches +Hash+ containing +key+. + # + # @param [Object] key expected key. + # @return [HasKey] parameter matcher. + # + # @see Expectation#with + # + # @example Actual parameter contains entry with expected key. # object = mock() # object.expects(:method_1).with(has_key('key_1')) # object.method_1('key_1' => 1, 'key_2' => 2) # # no error raised # + # @example Actual parameter does not contain entry with expected key. # object = mock() # object.expects(:method_1).with(has_key('key_1')) # object.method_1('key_2' => 2) @@ -20,24 +26,28 @@ def has_key(key) HasKey.new(key) end - class HasKey < Base # :nodoc: - + # Parameter matcher which matches when actual parameter contains +Hash+ entry with expected key. + class HasKey < Base + + # @private def initialize(key) @key = key end - + + # @private def matches?(available_parameters) parameter = available_parameters.shift return false unless parameter.respond_to?(:keys) parameter.keys.any? { |key| @key.to_matcher.matches?([key]) } end - + + # @private def mocha_inspect "has_key(#{@key.mocha_inspect})" end - + end - + end - -end \ No newline at end of file + +end diff --git a/lib/mocha/parameter_matchers/has_value.rb b/lib/mocha/parameter_matchers/has_value.rb index 16c8b4d2d..cfed085cf 100644 --- a/lib/mocha/parameter_matchers/has_value.rb +++ b/lib/mocha/parameter_matchers/has_value.rb @@ -1,17 +1,23 @@ require 'mocha/parameter_matchers/base' module Mocha - + module ParameterMatchers - # :call-seq: has_value(value) -> parameter_matcher - # # Matches +Hash+ containing +value+. + # + # @param [Object] value expected value. + # @return [HasValue] parameter matcher. + # + # @see Expectation#with + # + # @example Actual parameter contains entry with expected value. # object = mock() # object.expects(:method_1).with(has_value(1)) # object.method_1('key_1' => 1, 'key_2' => 2) # # no error raised # + # @example Actual parameter does not contain entry with expected value. # object = mock() # object.expects(:method_1).with(has_value(1)) # object.method_1('key_2' => 2) @@ -20,24 +26,28 @@ def has_value(value) HasValue.new(value) end - class HasValue < Base # :nodoc: - + # Parameter matcher which matches when actual parameter contains +Hash+ entry with expected value. + class HasValue < Base + + # @private def initialize(value) @value = value end - + + # @private def matches?(available_parameters) parameter = available_parameters.shift return false unless parameter.respond_to?(:values) parameter.values.any? { |value| @value.to_matcher.matches?([value]) } end - + + # @private def mocha_inspect "has_value(#{@value.mocha_inspect})" end - + end - + end - -end \ No newline at end of file + +end diff --git a/lib/mocha/parameter_matchers/includes.rb b/lib/mocha/parameter_matchers/includes.rb index 2717503c0..24ce0d347 100644 --- a/lib/mocha/parameter_matchers/includes.rb +++ b/lib/mocha/parameter_matchers/includes.rb @@ -1,35 +1,45 @@ require 'mocha/parameter_matchers/base' module Mocha - + module ParameterMatchers - # :call-seq: includes(item) -> parameter_matcher + # Matches any object that responds with +true+ to +include?(item)+. + # + # @param [Object] item expected item. + # @return [Includes] parameter matcher. + # + # @see Expectation#with # - # Matches any object that responds true to include?(item) + # @example Actual parameter includes item. # object = mock() # object.expects(:method_1).with(includes('foo')) # object.method_1(['foo', 'bar']) # # no error raised # + # @example Actual parameter does not include item. # object.method_1(['baz']) # # error raised, because ['baz'] does not include 'foo'. def includes(item) Includes.new(item) end - class Includes < Base # :nodoc: + # Parameter matcher which matches when actual parameter includes expected value. + class Includes < Base + # @private def initialize(item) @item = item end + # @private def matches?(available_parameters) parameter = available_parameters.shift return false unless parameter.respond_to?(:include?) return parameter.include?(@item) end + # @private def mocha_inspect "includes(#{@item.mocha_inspect})" end diff --git a/lib/mocha/parameter_matchers/instance_of.rb b/lib/mocha/parameter_matchers/instance_of.rb index 49b4a478d..0c9090931 100644 --- a/lib/mocha/parameter_matchers/instance_of.rb +++ b/lib/mocha/parameter_matchers/instance_of.rb @@ -1,17 +1,24 @@ require 'mocha/parameter_matchers/base' module Mocha - + module ParameterMatchers - # :call-seq: instance_of(klass) -> parameter_matcher - # # Matches any object that is an instance of +klass+ + # + # @param [Class] klass expected class. + # @return [InstanceOf] parameter matcher. + # + # @see Expectation#with + # @see Kernel#instance_of? + # + # @example Actual parameter is an instance of +String+. # object = mock() # object.expects(:method_1).with(instance_of(String)) # object.method_1('string') # # no error raised # + # @example Actual parameter is not an instance of +String+. # object = mock() # object.expects(:method_1).with(instance_of(String)) # object.method_1(99) @@ -19,24 +26,28 @@ module ParameterMatchers def instance_of(klass) InstanceOf.new(klass) end - - class InstanceOf < Base # :nodoc: - + + # Parameter matcher which matches when actual parameter is an instance of the specified class. + class InstanceOf < Base + + # @private def initialize(klass) @klass = klass end - + + # @private def matches?(available_parameters) parameter = available_parameters.shift parameter.instance_of?(@klass) end - + + # @private def mocha_inspect "instance_of(#{@klass.mocha_inspect})" end - + end - + end - -end \ No newline at end of file + +end diff --git a/lib/mocha/parameter_matchers/is_a.rb b/lib/mocha/parameter_matchers/is_a.rb index a721db523..493e84c30 100644 --- a/lib/mocha/parameter_matchers/is_a.rb +++ b/lib/mocha/parameter_matchers/is_a.rb @@ -1,17 +1,24 @@ require 'mocha/parameter_matchers/base' module Mocha - + module ParameterMatchers - # :call-seq: is_a(klass) -> parameter_matcher + # Matches any object that is a +klass+. + # + # @param [Class] klass expected class. + # @return [IsA] parameter matcher. + # + # @see Expectation#with + # @see Kernel#is_a? # - # Matches any object that is a +klass+ + # @example Actual parameter is a +Integer+. # object = mock() # object.expects(:method_1).with(is_a(Integer)) # object.method_1(99) # # no error raised # + # @example Actual parameter is not a +Integer+. # object = mock() # object.expects(:method_1).with(is_a(Integer)) # object.method_1('string') @@ -19,24 +26,28 @@ module ParameterMatchers def is_a(klass) IsA.new(klass) end - - class IsA < Base # :nodoc: - + + # Parameter matcher which matches when actual parameter is a specific class. + class IsA < Base + + # @private def initialize(klass) @klass = klass end - + + # @private def matches?(available_parameters) parameter = available_parameters.shift parameter.is_a?(@klass) end - + + # @private def mocha_inspect "is_a(#{@klass.mocha_inspect})" end - + end - + end - -end \ No newline at end of file + +end diff --git a/lib/mocha/parameter_matchers/kind_of.rb b/lib/mocha/parameter_matchers/kind_of.rb index 710d709d0..cb9edd18c 100644 --- a/lib/mocha/parameter_matchers/kind_of.rb +++ b/lib/mocha/parameter_matchers/kind_of.rb @@ -1,17 +1,24 @@ require 'mocha/parameter_matchers/base' module Mocha - + module ParameterMatchers - # :call-seq: kind_of(klass) -> parameter_matcher + # Matches any +Object+ that is a kind of +klass+. + # + # @param [Class] klass expected class. + # @return [KindOf] parameter matcher. + # + # @see Expectation#with + # @see Kernel#kind_of? # - # Matches any object that is a kind of +klass+ + # @example Actual parameter is a kind of +Integer+. # object = mock() # object.expects(:method_1).with(kind_of(Integer)) # object.method_1(99) # # no error raised # + # @example Actual parameter is not a kind of +Integer+. # object = mock() # object.expects(:method_1).with(kind_of(Integer)) # object.method_1('string') @@ -19,24 +26,28 @@ module ParameterMatchers def kind_of(klass) KindOf.new(klass) end - - class KindOf < Base # :nodoc: - + + # Parameter matcher which matches when actual parameter is a kind of specified class. + class KindOf < Base + + # @private def initialize(klass) @klass = klass end - + + # @private def matches?(available_parameters) parameter = available_parameters.shift parameter.kind_of?(@klass) end - + + # @private def mocha_inspect "kind_of(#{@klass.mocha_inspect})" end - + end - + end - -end \ No newline at end of file + +end diff --git a/lib/mocha/parameter_matchers/not.rb b/lib/mocha/parameter_matchers/not.rb index 7a9cf2714..d13e7938a 100644 --- a/lib/mocha/parameter_matchers/not.rb +++ b/lib/mocha/parameter_matchers/not.rb @@ -1,17 +1,23 @@ require 'mocha/parameter_matchers/base' module Mocha - + module ParameterMatchers - # :call-seq: Not(parameter_matcher) -> parameter_matcher + # Matches if +matcher+ does *not* match. + # + # @param [Base] matcher matcher whose logic to invert. + # @return [Not] parameter matcher. + # + # @see Expectation#with # - # Matches if +parameter_matcher+ does not match. + # @example Actual parameter does not include the value +1+. # object = mock() # object.expects(:method_1).with(Not(includes(1))) # object.method_1([0, 2, 3]) # # no error raised # + # @example Actual parameter does include the value +1+. # object = mock() # object.expects(:method_1).with(Not(includes(1))) # object.method_1([0, 1, 2, 3]) @@ -19,24 +25,28 @@ module ParameterMatchers def Not(matcher) Not.new(matcher) end - - class Not < Base # :nodoc: - + + # Parameter matcher which inverts the logic of the specified matcher using a logical NOT operation. + class Not < Base + + # @private def initialize(matcher) @matcher = matcher end - + + # @private def matches?(available_parameters) parameter = available_parameters.shift !@matcher.matches?([parameter]) end - + + # @private def mocha_inspect "Not(#{@matcher.mocha_inspect})" end - + end - + end - -end \ No newline at end of file + +end diff --git a/lib/mocha/parameter_matchers/object.rb b/lib/mocha/parameter_matchers/object.rb index 56a194036..9d646f095 100644 --- a/lib/mocha/parameter_matchers/object.rb +++ b/lib/mocha/parameter_matchers/object.rb @@ -1,15 +1,17 @@ require 'mocha/parameter_matchers/equals' module Mocha - + module ObjectMethods - def to_matcher # :nodoc: + # @private + def to_matcher Mocha::ParameterMatchers::Equals.new(self) end end - + end +# @private class Object include Mocha::ObjectMethods end diff --git a/lib/mocha/parameter_matchers/optionally.rb b/lib/mocha/parameter_matchers/optionally.rb index fc2c3a948..3ec098ce6 100644 --- a/lib/mocha/parameter_matchers/optionally.rb +++ b/lib/mocha/parameter_matchers/optionally.rb @@ -1,25 +1,33 @@ module Mocha - + module ParameterMatchers - # :call-seq: optionally(*parameter_matchers) -> parameter_matcher - # # Matches optional parameters if available. + # + # @param [*Array] matchers matchers for optional parameters. + # @return [Optionally] parameter matcher. + # + # @see Expectation#with + # + # @example Only the two required parameters are supplied and they both match their expected value. # object = mock() # object.expects(:method_1).with(1, 2, optionally(3, 4)) # object.method_1(1, 2) # # no error raised # + # @example Both required parameters and one of the optional parameters are supplied and they all match their expected value. # object = mock() # object.expects(:method_1).with(1, 2, optionally(3, 4)) # object.method_1(1, 2, 3) # # no error raised # + # @example Both required parameters and both of the optional parameters are supplied and they all match their expected value. # object = mock() # object.expects(:method_1).with(1, 2, optionally(3, 4)) # object.method_1(1, 2, 3, 4) # # no error raised # + # @example One of the actual optional parameters does not match the expected value. # object = mock() # object.expects(:method_1).with(1, 2, optionally(3, 4)) # object.method_1(1, 2, 3, 5) @@ -27,13 +35,16 @@ module ParameterMatchers def optionally(*matchers) Optionally.new(*matchers) end - - class Optionally < Base # :nodoc: - + + # Parameter matcher which allows optional parameters to be specified. + class Optionally < Base + + # @private def initialize(*parameters) @matchers = parameters.map { |parameter| parameter.to_matcher } end - + + # @private def matches?(available_parameters) index = 0 while (available_parameters.length > 0) && (index < @matchers.length) do @@ -43,13 +54,14 @@ def matches?(available_parameters) end return true end - + + # @private def mocha_inspect "optionally(#{@matchers.map { |matcher| matcher.mocha_inspect }.join(", ") })" end - + end - + end - -end \ No newline at end of file + +end diff --git a/lib/mocha/parameter_matchers/query_string.rb b/lib/mocha/parameter_matchers/query_string.rb index 4098c3de3..e6c11c744 100644 --- a/lib/mocha/parameter_matchers/query_string.rb +++ b/lib/mocha/parameter_matchers/query_string.rb @@ -4,14 +4,20 @@ module Mocha module ParameterMatchers - # :call-seq: has_equivalent_query_string(uri) -> parameter_matcher + # Matches a URI without regard to the ordering of parameters in the query string. # - # Matches a URI without regard to the ordering of parameters in the query string + # @param [String] uri URI to match. + # @return [QueryStringMatches] parameter matcher. + # + # @see Expectation#with + # + # @example Actual URI has equivalent query string. # object = mock() # object.expects(:method_1).with(has_equivalent_query_string('http://example.com/foo?a=1&b=2)) # object.method_1('http://example.com/foo?b=2&a=1') # # no error raised # + # @example Actual URI does not have equivalent query string. # object = mock() # object.expects(:method_1).with(has_equivalent_query_string('http://example.com/foo?a=1&b=2)) # object.method_1('http://example.com/foo?a=1&b=3') @@ -20,23 +26,28 @@ def has_equivalent_query_string(uri) QueryStringMatches.new(uri) end - class QueryStringMatches < Base # :nodoc: + # Parameter matcher which matches URIs with equivalent query strings. + class QueryStringMatches < Base + # @private def initialize(uri) @uri = URI.parse(uri) end + # @private def matches?(available_parameters) actual = explode(URI.parse(available_parameters.shift)) expected = explode(@uri) actual == expected end + # @private def mocha_inspect "has_equivalent_query_string(#{@uri.mocha_inspect})" end private + # @private def explode(uri) query_hash = (uri.query || '').split('&').inject({}){ |h, kv| h.merge(Hash[*kv.split('=')]) } URI::Generic::COMPONENT.inject({}){ |h, k| h.merge(k => uri.__send__(k)) }.merge(:query => query_hash) diff --git a/lib/mocha/parameter_matchers/regexp_matches.rb b/lib/mocha/parameter_matchers/regexp_matches.rb index 65a5be939..5c8f44d99 100644 --- a/lib/mocha/parameter_matchers/regexp_matches.rb +++ b/lib/mocha/parameter_matchers/regexp_matches.rb @@ -1,17 +1,23 @@ require 'mocha/parameter_matchers/base' module Mocha - + module ParameterMatchers - # :call-seq: regexp_matches(regular_expression) -> parameter_matcher + # Matches any object that matches +regexp+. + # + # @param [Regexp] regexp regular expression to match. + # @return [RegexpMatches] parameter matcher. + # + # @see Expectation#with # - # Matches any object that matches +regular_expression+. + # @example Actual parameter is matched by specified regular expression. # object = mock() # object.expects(:method_1).with(regexp_matches(/e/)) # object.method_1('hello') # # no error raised # + # @example Actual parameter is not matched by specified regular expression. # object = mock() # object.expects(:method_1).with(regexp_matches(/a/)) # object.method_1('hello') @@ -21,24 +27,28 @@ def regexp_matches(regexp) RegexpMatches.new(regexp) end - class RegexpMatches < Base # :nodoc: - + # Parameter matcher which matches if specified regular expression matches actual paramter. + class RegexpMatches < Base + + # @private def initialize(regexp) @regexp = regexp end - + + # @private def matches?(available_parameters) parameter = available_parameters.shift return false unless parameter.respond_to?(:=~) parameter =~ @regexp end - + + # @private def mocha_inspect "regexp_matches(#{@regexp.mocha_inspect})" end - + end - + end - + end diff --git a/lib/mocha/parameter_matchers/responds_with.rb b/lib/mocha/parameter_matchers/responds_with.rb index 4355796fb..12fe0b419 100644 --- a/lib/mocha/parameter_matchers/responds_with.rb +++ b/lib/mocha/parameter_matchers/responds_with.rb @@ -5,14 +5,21 @@ module Mocha module ParameterMatchers - # :call-seq: responds_with(message, result) -> parameter_matcher - # # Matches any object that responds to +message+ with +result+. To put it another way, it tests the quack, not the duck. + # + # @param [Symbol] message method to invoke. + # @param [Object] result expected result of sending +message+. + # @return [RespondsWith] parameter matcher. + # + # @see Expectation#with + # + # @example Actual parameter responds with "FOO" when :upcase is invoked. # object = mock() # object.expects(:method_1).with(responds_with(:upcase, "FOO")) # object.method_1("foo") # # no error raised, because "foo".upcase == "FOO" # + # @example Actual parameter does not respond with "FOO" when :upcase is invoked. # object = mock() # object.expects(:method_1).with(responds_with(:upcase, "BAR")) # object.method_1("foo") @@ -21,23 +28,27 @@ def responds_with(message, result) RespondsWith.new(message, result) end - class RespondsWith < Base # :nodoc: + # Parameter matcher which matches if actual parameter returns expected result when specified method is invoked. + class RespondsWith < Base + # @private def initialize(message, result) @message, @result = message, result end + # @private def matches?(available_parameters) parameter = available_parameters.shift parameter.__send__(@message) == @result end + # @private def mocha_inspect "responds_with(#{@message.mocha_inspect}, #{@result.mocha_inspect})" end - + end - + end - + end diff --git a/lib/mocha/parameter_matchers/yaml_equivalent.rb b/lib/mocha/parameter_matchers/yaml_equivalent.rb index 6449717c9..ea3f11651 100644 --- a/lib/mocha/parameter_matchers/yaml_equivalent.rb +++ b/lib/mocha/parameter_matchers/yaml_equivalent.rb @@ -5,14 +5,20 @@ module Mocha module ParameterMatchers - # :call-seq: yaml_equivalent(object) -> parameter_matcher - # # Matches any YAML that represents the specified +object+ + # + # @param [Object] object object whose YAML to compare. + # @return [YamlEquivalent] parameter matcher. + # + # @see Expectation#with + # + # @example Actual parameter is YAML equivalent of specified +object+. # object = mock() # object.expects(:method_1).with(yaml_equivalent(1, 2, 3)) # object.method_1("--- \n- 1\n- 2\n- 3\n") # # no error raised # + # @example Actual parameter is not YAML equivalent of specified +object+. # object = mock() # object.expects(:method_1).with(yaml_equivalent(1, 2, 3)) # object.method_1("--- \n- 1\n- 2\n") @@ -21,23 +27,27 @@ def yaml_equivalent(object) YamlEquivalent.new(object) end - class YamlEquivalent < Base # :nodoc: + # Parameter matcher which matches if actual parameter is YAML equivalent of specified object. + class YamlEquivalent < Base + # @private def initialize(object) @object = object end + # @private def matches?(available_parameters) parameter = available_parameters.shift @object == YAML.load(parameter) end + # @private def mocha_inspect "yaml_equivalent(#{@object.mocha_inspect})" end - + end - + end - + end diff --git a/lib/mocha/sequence.rb b/lib/mocha/sequence.rb index ed9852e0c..2c12d3c6b 100644 --- a/lib/mocha/sequence.rb +++ b/lib/mocha/sequence.rb @@ -1,42 +1,51 @@ -module Mocha # :nodoc: - +module Mocha + + # Used to constrain the order in which expectations can occur. + # + # @see API#sequence + # @see Expectation#in_sequence class Sequence - + + # @private class InSequenceOrderingConstraint - + def initialize(sequence, index) @sequence, @index = sequence, index end - + def allows_invocation_now? @sequence.satisfied_to_index?(@index) end - + def mocha_inspect "in sequence #{@sequence.mocha_inspect}" end - + end - + + # @private def initialize(name) @name = name @expectations = [] end - + + # @private def constrain_as_next_in_sequence(expectation) index = @expectations.length @expectations << expectation expectation.add_ordering_constraint(InSequenceOrderingConstraint.new(self, index)) end - + + # @private def satisfied_to_index?(index) @expectations[0...index].all? { |expectation| expectation.satisfied? } end - + + # @private def mocha_inspect "#{@name.mocha_inspect}" end - + end - -end \ No newline at end of file + +end diff --git a/lib/mocha/state_machine.rb b/lib/mocha/state_machine.rb index 1b9781a7d..603c75e3b 100644 --- a/lib/mocha/state_machine.rb +++ b/lib/mocha/state_machine.rb @@ -1,91 +1,106 @@ -module Mocha # :nodoc: +module Mocha # A state machine that is used to constrain the order of invocations. - # An invocation can be constrained to occur when a state is, or is_not, active. + # An invocation can be constrained to occur when a state {#is}, or {#is_not}, active. class StateMachine - - class State # :nodoc: - + + # Provides a mechanism to change the state of a {StateMachine} at some point in the future. + class State + + # @private def initialize(state_machine, state) @state_machine, @state = state_machine, state end - + + # @private def activate @state_machine.current_state = @state end - + + # @private def active? @state_machine.current_state == @state end - + + # @private def mocha_inspect "#{@state_machine.name} is #{@state.mocha_inspect}" end - + end - - class StatePredicate # :nodoc: - + + # Provides the ability to determine whether a {StateMachine} is in a specified state at some point in the future. + class StatePredicate + + # @private def initialize(state_machine, state) @state_machine, @state = state_machine, state end - + + # @private def active? @state_machine.current_state != @state end - + + # @private def mocha_inspect "#{@state_machine.name} is not #{@state.mocha_inspect}" end - + end - - attr_reader :name # :nodoc: - - attr_accessor :current_state # :nodoc: - - def initialize(name) # :nodoc: + + # @private + attr_reader :name + + # @private + attr_accessor :current_state + + # @private + def initialize(name) @name = name @current_state = nil end - - # :call-seq: starts_as(initial_state) -> state_machine + + # Put the {StateMachine} into the state specified by +initial_state_name+. # - # Put the +state_machine+ into the +initial_state+. - def starts_as(initial_state) - become(initial_state) + # @param [String] initial_state_name name of initial state + # @return [StateMachine] state machine, thereby allowing invocations of other {StateMachine} methods to be chained. + def starts_as(initial_state_name) + become(initial_state_name) self end - - # :call-seq: become(next_state) + + # Put the {StateMachine} into the +next_state_name+. # - # Put the +state_machine+ into the +next_state+. - def become(next_state) - @current_state = next_state + # @param [String] next_state_name name of new state + def become(next_state_name) + @current_state = next_state_name end - - # :call-seq: is(state) + + # Provides a mechanism to change the {StateMachine} into the state specified by +state_name+ at some point in the future. # - # Determines whether the +state_machine+ is in the specified +state+. - def is(state) - State.new(self, state) - end - - # :call-seq: is_not(state) + # Or provides a mechanism to determine whether the {StateMachine} is in the state specified by +state_name+ at some point in the future. # - # Determines whether the +state_machine+ is not in the specified +state+. - def is_not(state) - StatePredicate.new(self, state) + # @param [String] state_name name of new state + # @return [State] state which, when activated, will change the {StateMachine} into the state with the specified +state_name+. + def is(state_name) + State.new(self, state_name) + end + + # Provides a mechanism to determine whether the {StateMachine} is not in the state specified by +state_name+ at some point in the future. + def is_not(state_name) + StatePredicate.new(self, state_name) end - - def mocha_inspect # :nodoc: + + # @private + def mocha_inspect if @current_state "#{@name} is #{@current_state.mocha_inspect}" else "#{@name} has no current state" end end - + end -end \ No newline at end of file +end diff --git a/lib/mocha/stubbing_error.rb b/lib/mocha/stubbing_error.rb index 34be28996..3bd27efa7 100644 --- a/lib/mocha/stubbing_error.rb +++ b/lib/mocha/stubbing_error.rb @@ -1,10 +1,11 @@ require 'mocha/backtrace_filter' -module Mocha # :nodoc: - - # Exception raised when an action prevented by Configuration#prevent is attempted. +module Mocha + + # Exception raised when an action prevented by {Configuration.prevent} is attempted. class StubbingError < StandardError + # @private def initialize(message = nil, backtrace = []) # :nodoc: super(message) filter = BacktraceFilter.new @@ -12,5 +13,5 @@ def initialize(message = nil, backtrace = []) # :nodoc: end end - + end diff --git a/mocha.gemspec b/mocha.gemspec index 9394f5b97..d66b915ea 100644 --- a/mocha.gemspec +++ b/mocha.gemspec @@ -30,17 +30,20 @@ Gem::Specification.new do |s| s.add_development_dependency("rake", ">= 0") s.add_development_dependency("introspection", "~> 0.0.1") s.add_development_dependency("rdoc", "~> 3.1") + s.add_development_dependency("yard") s.add_development_dependency("coderay", "~> 0.1") else s.add_dependency("rake", ">= 0") s.add_dependency("introspection", "~> 0.0.1") s.add_dependency("rdoc", "~> 3.1") + s.add_dependency("yard") s.add_dependency("coderay", "~> 0.1") end else s.add_dependency("rake", ">= 0") s.add_dependency("introspection", "~> 0.0.1") s.add_dependency("rdoc", "~> 3.1") + s.add_dependency("yard") s.add_dependency("coderay", "~> 0.1") end end