summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--test/lib/mocha.rb19
-rw-r--r--test/lib/mocha/any_instance_method.rb35
-rw-r--r--test/lib/mocha/auto_verify.rb113
-rw-r--r--test/lib/mocha/central.rb35
-rw-r--r--test/lib/mocha/class_method.rb62
-rw-r--r--test/lib/mocha/expectation.rb295
-rw-r--r--test/lib/mocha/expectation_error.rb6
-rw-r--r--test/lib/mocha/infinite_range.rb27
-rw-r--r--test/lib/mocha/inspect.rb37
-rw-r--r--test/lib/mocha/instance_method.rb8
-rw-r--r--test/lib/mocha/metaclass.rb7
-rw-r--r--test/lib/mocha/mock.rb20
-rw-r--r--test/lib/mocha/mock_methods.rb122
-rw-r--r--test/lib/mocha/object.rb100
-rw-r--r--test/lib/mocha/pretty_parameters.rb28
-rw-r--r--test/lib/mocha/setup_and_teardown.rb23
-rw-r--r--test/lib/mocha/standalone.rb30
-rw-r--r--test/lib/mocha/test_case_adapter.rb49
-rw-r--r--test/lib/mocha_standalone.rb2
-rw-r--r--test/lib/stubba.rb2
-rw-r--r--test/ral/providers/package/apt.rb68
-rw-r--r--test/ral/providers/package/aptitude.rb65
-rw-r--r--test/ral/providers/package/dpkg.rb61
23 files changed, 1214 insertions, 0 deletions
diff --git a/test/lib/mocha.rb b/test/lib/mocha.rb
new file mode 100644
index 000000000..58571156a
--- /dev/null
+++ b/test/lib/mocha.rb
@@ -0,0 +1,19 @@
+require 'mocha_standalone'
+require 'mocha/test_case_adapter'
+
+require 'test/unit/testcase'
+
+module Test
+
+ module Unit
+
+ class TestCase
+
+ include Mocha::Standalone
+ include Mocha::TestCaseAdapter
+
+ end
+
+ end
+
+end \ No newline at end of file
diff --git a/test/lib/mocha/any_instance_method.rb b/test/lib/mocha/any_instance_method.rb
new file mode 100644
index 000000000..4d55293b9
--- /dev/null
+++ b/test/lib/mocha/any_instance_method.rb
@@ -0,0 +1,35 @@
+require 'mocha/class_method'
+
+module Mocha
+
+ class AnyInstanceMethod < ClassMethod
+
+ def unstub
+ remove_new_method
+ restore_original_method
+ stubbee.any_instance.reset_mocha
+ end
+
+ def mock
+ stubbee.any_instance.mocha
+ end
+
+ def hide_original_method
+ stubbee.class_eval "alias_method :#{hidden_method}, :#{method}" if stubbee.method_defined?(method)
+ end
+
+ def define_new_method
+ stubbee.class_eval "def #{method}(*args, &block); self.class.any_instance.mocha.method_missing(:#{method}, *args, &block); end"
+ end
+
+ def remove_new_method
+ stubbee.class_eval "remove_method :#{method}"
+ end
+
+ def restore_original_method
+ stubbee.class_eval "alias_method :#{method}, :#{hidden_method}; remove_method :#{hidden_method}" if stubbee.method_defined?(hidden_method)
+ end
+
+ end
+
+end \ No newline at end of file
diff --git a/test/lib/mocha/auto_verify.rb b/test/lib/mocha/auto_verify.rb
new file mode 100644
index 000000000..7aa5e8b30
--- /dev/null
+++ b/test/lib/mocha/auto_verify.rb
@@ -0,0 +1,113 @@
+require 'mocha/mock'
+
+# Methods added to TestCase allowing creation of mock objects.
+#
+# Mocks created this way will have their expectations automatically verified at the end of the test.
+#
+# See Mocha::MockMethods for methods on mock objects.
+module Mocha
+
+ module AutoVerify
+
+ def mocks # :nodoc:
+ @mocks ||= []
+ end
+
+ def reset_mocks # :nodoc:
+ @mocks = nil
+ end
+
+ # :call-seq: mock(name) -> mock object
+ # mock(expected_methods = {}) -> mock object
+ # mock(name, expected_methods = {}) -> 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 <b>must</b> 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
+ def mock(*args)
+ name, expectations = name_and_expectations_from_args(args)
+ build_mock_with_expectations(:expects, expectations, name)
+ end
+
+ # :call-seq: stub(name) -> mock object
+ # stub(stubbed_methods = {}) -> mock object
+ # stub(name, stubbed_methods = {}) -> 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 <b>need not</b> 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
+ # end
+ def stub(*args)
+ name, expectations = name_and_expectations_from_args(args)
+ build_mock_with_expectations(:stubs, expectations, name)
+ end
+
+ # :call-seq: stub_everything(name) -> mock object
+ # stub_everything(stubbed_methods = {}) -> mock object
+ # stub_everything(name, stubbed_methods = {}) -> mock object
+ #
+ # Creates a mock object that accepts calls to any method.
+ #
+ # By default it will return +nil+ for any method call.
+ #
+ # +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
+ # end
+ def stub_everything(*args)
+ name, expectations = name_and_expectations_from_args(args)
+ build_mock_with_expectations(:stub_everything, expectations, name)
+ end
+
+ def verify_mocks # :nodoc:
+ mocks.each { |mock| mock.verify { yield if block_given? } }
+ end
+
+ def teardown_mocks # :nodoc:
+ reset_mocks
+ end
+
+ def build_mock_with_expectations(expectation_type = :expects, expectations = {}, name = nil) # :nodoc:
+ stub_everything = (expectation_type == :stub_everything)
+ expectation_type = :stubs if expectation_type == :stub_everything
+ mock = Mocha::Mock.new(stub_everything, name)
+ expectations.each do |method, result|
+ mock.__send__(expectation_type, method).returns(result)
+ end
+ mocks << mock
+ mock
+ end
+
+ private
+
+ def name_and_expectations_from_args(args) # :nodoc:
+ name = args.first.is_a?(String) ? args.delete_at(0) : nil
+ expectations = args.first || {}
+ [name, expectations]
+ end
+
+ end
+
+end \ No newline at end of file
diff --git a/test/lib/mocha/central.rb b/test/lib/mocha/central.rb
new file mode 100644
index 000000000..3dde7350f
--- /dev/null
+++ b/test/lib/mocha/central.rb
@@ -0,0 +1,35 @@
+module Mocha
+
+ class Central
+
+ attr_accessor :stubba_methods
+
+ def initialize
+ self.stubba_methods = []
+ end
+
+ def stub(method)
+ unless stubba_methods.include?(method)
+ method.stub
+ stubba_methods.push method
+ end
+ end
+
+ def verify_all(&block)
+ unique_mocks.each { |mock| mock.verify(&block) }
+ end
+
+ def unique_mocks
+ stubba_methods.inject({}) { |mocks, method| mocks[method.mock.__id__] = method.mock; mocks }.values
+ end
+
+ def unstub_all
+ while stubba_methods.size > 0
+ method = stubba_methods.pop
+ method.unstub
+ end
+ end
+
+ end
+
+end \ No newline at end of file
diff --git a/test/lib/mocha/class_method.rb b/test/lib/mocha/class_method.rb
new file mode 100644
index 000000000..915fe71b5
--- /dev/null
+++ b/test/lib/mocha/class_method.rb
@@ -0,0 +1,62 @@
+require 'mocha/metaclass'
+
+module Mocha
+
+ class ClassMethod
+
+ attr_reader :stubbee, :method
+
+ def initialize(stubbee, method)
+ @stubbee, @method = stubbee, method
+ end
+
+ def stub
+ hide_original_method
+ define_new_method
+ end
+
+ def unstub
+ remove_new_method
+ restore_original_method
+ stubbee.reset_mocha
+ end
+
+ def mock
+ stubbee.mocha
+ end
+
+ def hide_original_method
+ stubbee.__metaclass__.class_eval "alias_method :#{hidden_method}, :#{method}" if stubbee.__metaclass__.method_defined?(method)
+ end
+
+ def define_new_method
+ stubbee.__metaclass__.class_eval "def #{method}(*args, &block); mocha.method_missing(:#{method}, *args, &block); end"
+ end
+
+ def remove_new_method
+ stubbee.__metaclass__.class_eval "remove_method :#{method}"
+ end
+
+ def restore_original_method
+ stubbee.__metaclass__.class_eval "alias_method :#{method}, :#{hidden_method}; remove_method :#{hidden_method}" if stubbee.__metaclass__.method_defined?(hidden_method)
+ end
+
+ def hidden_method
+ method_name = method.to_s.gsub(/\W/) {|s| "_substituted_character_#{s[0]}_" }
+ "__stubba__#{method_name}__stubba__"
+ end
+
+ def eql?(other)
+ return false unless (other.class == self.class)
+ (stubbee == other.stubbee) and (method == other.method)
+ end
+
+ alias_method :==, :eql?
+
+ def to_s
+ "#{stubbee}.#{method}"
+ end
+
+ end
+
+end \ No newline at end of file
diff --git a/test/lib/mocha/expectation.rb b/test/lib/mocha/expectation.rb
new file mode 100644
index 000000000..0073c1e13
--- /dev/null
+++ b/test/lib/mocha/expectation.rb
@@ -0,0 +1,295 @@
+require 'mocha/infinite_range'
+require 'mocha/pretty_parameters'
+require 'mocha/expectation_error'
+
+class Object
+
+ alias_method :__is_a__, :is_a?
+
+end
+
+module Mocha
+ # Methods on expectations returned from Mocha::MockMethods#expects and Mocha::MockMethods#stubs
+ class Expectation
+
+ # :stopdoc:
+
+ class InvalidExpectation < Exception; end
+
+ class AlwaysEqual
+ def ==(other)
+ true
+ end
+ end
+
+ attr_reader :method_name, :backtrace
+
+ def initialize(mock, method_name, backtrace = nil)
+ @mock, @method_name = mock, method_name
+ @count = 1
+ @parameters, @parameter_block = AlwaysEqual.new, nil
+ @invoked, @return_value = 0, nil
+ @backtrace = backtrace || caller
+ @yield = nil
+ end
+
+ def yield?
+ @yield
+ end
+
+ def match?(method_name, *arguments)
+ if @parameter_block then
+ @parameter_block.call(*arguments)
+ else
+ (@method_name == method_name) and (@parameters == arguments)
+ end
+ end
+
+ # :startdoc:
+
+ # :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
+ # object = mock()
+ # object.expects(:expected_method).times(3)
+ # 3.times { object.expected_method } # => verify succeeds
+ #
+ # object = mock()
+ # object.expects(:expected_method).times(3)
+ # 2.times { object.expected_method } # => verify fails
+ #
+ # object = mock()
+ # object.expects(:expected_method).times(2..4)
+ # 3.times { object.expected_method } # => verify succeeds
+ #
+ # object = mock()
+ # object.expects(:expected_method).times(2..4)
+ # object.expected_method # => verify fails
+ def times(range)
+ @count = range
+ self
+ end
+
+ # :call-seq: never -> expectation
+ #
+ # Modifies expectation so that the expected method must never be called.
+ # object = mock()
+ # object.expects(:expected_method).never
+ # object.expected_method # => verify fails
+ #
+ # object = mock()
+ # object.expects(:expected_method).never
+ # object.expected_method # => verify succeeds
+ def never
+ times(0)
+ 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+.
+ # object = mock()
+ # object.expects(:expected_method).at_least(2)
+ # 3.times { object.expected_method } # => verify succeeds
+ #
+ # object = mock()
+ # object.expects(:expected_method).at_least(2)
+ # object.expected_method # => verify fails
+ def at_least(minimum_number_of_times)
+ times(Range.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.
+ # object = mock()
+ # object.expects(:expected_method).at_least_once
+ # object.expected_method # => verify succeeds
+ #
+ # object = mock()
+ # object.expects(:expected_method).at_least_once
+ # # => verify fails
+ def at_least_once()
+ at_least(1)
+ 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+.
+ # object = mock()
+ # object.expects(:expected_method).at_most(2)
+ # 2.times { object.expected_method } # => verify succeeds
+ #
+ # object = mock()
+ # object.expects(:expected_method).at_most(2)
+ # 3.times { object.expected_method } # => verify fails
+ def at_most(maximum_number_of_times)
+ times(Range.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.
+ # object = mock()
+ # object.expects(:expected_method).at_most_once
+ # object.expected_method # => verify succeeds
+ #
+ # object = mock()
+ # object.expects(:expected_method).at_most_once
+ # 2.times { object.expected_method } # => verify fails
+ def at_most_once()
+ at_most(1)
+ self
+ end
+
+ # :call-seq: with(*arguments, &parameter_block) -> expectation
+ #
+ # Modifies expectation so that the expected method must be called with specified +arguments+.
+ # object = mock()
+ # object.expects(:expected_method).with(:param1, :param2)
+ # object.expected_method(:param1, :param2) # => verify succeeds
+ #
+ # object = mock()
+ # object.expects(:expected_method).with(:param1, :param2)
+ # object.expected_method(:param3) # => verify fails
+ # If a +parameter_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+.
+ # object = mock()
+ # object.expects(:expected_method).with() { |value| value % 4 == 0 }
+ # object.expected_method(16) # => verify succeeds
+ #
+ # object = mock()
+ # object.expects(:expected_method).with() { |value| value % 4 == 0 }
+ # object.expected_method(17) # => verify fails
+ def with(*arguments, &parameter_block)
+ @parameters, @parameter_block = arguments, parameter_block
+ class << @parameters; def to_s; join(', '); end; end
+ self
+ end
+
+ # :call-seq: yields(*parameters) -> expectation
+ #
+ # Modifies expectation so that when the expected method is called, it yields with the specified +parameters+.
+ # object = mock()
+ # object.expects(:expected_method).yields('result')
+ # yielded_value = nil
+ # object.expected_method { |value| yielded_value = value }
+ # yielded_value # => 'result'
+ def yields(*parameters)
+ @yield = true
+ @parameters_to_yield = parameters
+ self
+ end
+
+ # :call-seq: returns(value) -> expectation
+ # :call-seq: returns(*values) -> expectation
+ #
+ # Modifies expectation so that when the expected method is called, it returns the specified +value+.
+ # 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.
+ # object = mock()
+ # object.stubs(:stubbed_method).returns(1, 2)
+ # object.stubbed_method # => 1
+ # object.stubbed_method # => 2
+ # If +value+ is a Proc, then expected method will return result of calling Proc.
+ # object = mock()
+ # object.stubs(:stubbed_method).returns(lambda { rand(100) })
+ # object.stubbed_method # => 41
+ # object.stubbed_method # => 77
+ def returns(*values)
+ @return_value = (values.size > 1) ? lambda { values.shift } : @return_value = values.first
+ 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+.
+ # object = mock()
+ # object.expects(:expected_method).raises(Exception, 'message')
+ # object.expected_method # => raises exception of class Exception and with message 'message'
+ def raises(exception = RuntimeError, message = nil)
+ @return_value = message ? lambda { raise exception, message } : lambda { raise exception }
+ self
+ end
+
+ # :stopdoc:
+
+ def invoke
+ @invoked += 1
+ yield(*@parameters_to_yield) if yield? and block_given?
+ @return_value.__is_a__(Proc) ? @return_value.call : @return_value
+ end
+
+ def verify
+ yield(self) if block_given?
+ unless (@count === @invoked) then
+ error = ExpectationError.new(error_message(@count, @invoked))
+ error.set_backtrace(filtered_backtrace)
+ raise error
+ end
+ end
+
+ def mocha_lib_directory
+ File.expand_path(File.join(File.dirname(__FILE__), "..")) + File::SEPARATOR
+ end
+
+ def filtered_backtrace
+ backtrace.reject { |location| Regexp.new(mocha_lib_directory).match(File.expand_path(location)) }
+ end
+
+ def method_signature
+ return "#{method_name}" if @parameters.__is_a__(AlwaysEqual)
+ "#{@method_name}(#{PrettyParameters.new(@parameters).pretty})"
+ end
+
+ def error_message(expected_count, actual_count)
+ "#{@mock.mocha_inspect}.#{method_signature} - expected calls: #{expected_count}, actual calls: #{actual_count}"
+ end
+
+ # :startdoc:
+
+ end
+
+ # :stopdoc:
+
+ class Stub < Expectation
+
+ def verify
+ true
+ end
+
+ end
+
+ class MissingExpectation < Expectation
+
+ def initialize(mock, method_name)
+ super
+ @invoked = true
+ end
+
+ def verify
+ msg = error_message(0, 1)
+ similar_expectations_list = similar_expectations.collect { |expectation| expectation.method_signature }.join("\n")
+ msg << "\nSimilar expectations:\n#{similar_expectations_list}" unless similar_expectations.empty?
+ error = ExpectationError.new(msg)
+ error.set_backtrace(filtered_backtrace)
+ raise error if @invoked
+ end
+
+ def similar_expectations
+ @mock.expectations.select { |expectation| expectation.method_name == self.method_name }
+ end
+
+ end
+
+ # :startdoc:
+
+end \ No newline at end of file
diff --git a/test/lib/mocha/expectation_error.rb b/test/lib/mocha/expectation_error.rb
new file mode 100644
index 000000000..c01482e63
--- /dev/null
+++ b/test/lib/mocha/expectation_error.rb
@@ -0,0 +1,6 @@
+module Mocha
+
+ class ExpectationError < StandardError
+ end
+
+end \ No newline at end of file
diff --git a/test/lib/mocha/infinite_range.rb b/test/lib/mocha/infinite_range.rb
new file mode 100644
index 000000000..144861ada
--- /dev/null
+++ b/test/lib/mocha/infinite_range.rb
@@ -0,0 +1,27 @@
+class Range
+
+ def self.at_least(minimum_value)
+ Range.new(minimum_value, infinite)
+ end
+
+ def self.at_most(maximum_value)
+ Range.new(-infinite, maximum_value, false)
+ end
+
+ def self.infinite
+ 1/0.0
+ end
+
+ alias_method :__to_s__, :to_s
+
+ def to_s
+ if first.to_f.infinite? then
+ return "at most #{last}"
+ elsif last.to_f.infinite? then
+ return "at least #{first}"
+ else
+ __to_s__
+ end
+ end
+
+end \ No newline at end of file
diff --git a/test/lib/mocha/inspect.rb b/test/lib/mocha/inspect.rb
new file mode 100644
index 000000000..fb3926b65
--- /dev/null
+++ b/test/lib/mocha/inspect.rb
@@ -0,0 +1,37 @@
+require 'date'
+
+class Object
+ def mocha_inspect
+ inspect =~ /#</ ? "#<#{self.class}:0x#{self.__id__.to_s(16)}>" : inspect
+ end
+end
+
+class String
+ def mocha_inspect
+ inspect.gsub(/\"/, "'")
+ end
+end
+
+class Array
+ def mocha_inspect
+ "[#{collect { |member| member.mocha_inspect }.join(', ')}]"
+ end
+end
+
+class Hash
+ def mocha_inspect
+ "{#{collect { |key, value| "#{key.mocha_inspect} => #{value.mocha_inspect}" }.join(', ')}}"
+ end
+end
+
+class Time
+ def mocha_inspect
+ "#{inspect} (#{to_f} secs)"
+ end
+end
+
+class Date
+ def mocha_inspect
+ to_s
+ end
+end \ No newline at end of file
diff --git a/test/lib/mocha/instance_method.rb b/test/lib/mocha/instance_method.rb
new file mode 100644
index 000000000..f0d4b04b8
--- /dev/null
+++ b/test/lib/mocha/instance_method.rb
@@ -0,0 +1,8 @@
+require 'mocha/class_method'
+
+module Mocha
+
+ class InstanceMethod < ClassMethod
+ end
+
+end \ No newline at end of file
diff --git a/test/lib/mocha/metaclass.rb b/test/lib/mocha/metaclass.rb
new file mode 100644
index 000000000..f78fb892b
--- /dev/null
+++ b/test/lib/mocha/metaclass.rb
@@ -0,0 +1,7 @@
+class Object
+
+ def __metaclass__
+ class << self; self; end
+ end
+
+end \ No newline at end of file
diff --git a/test/lib/mocha/mock.rb b/test/lib/mocha/mock.rb
new file mode 100644
index 000000000..1924aa89c
--- /dev/null
+++ b/test/lib/mocha/mock.rb
@@ -0,0 +1,20 @@
+require 'mocha/mock_methods'
+
+module Mocha
+
+ class Mock
+
+ include MockMethods
+
+ def initialize(stub_everything = false, name = nil)
+ @stub_everything = stub_everything
+ @mock_name = name
+ end
+
+ def mocha_inspect
+ @mock_name ? "#<Mock:#{@mock_name}>" : "#<Mock:0x#{__id__.to_s(16)}>"
+ end
+
+ end
+
+end \ No newline at end of file
diff --git a/test/lib/mocha/mock_methods.rb b/test/lib/mocha/mock_methods.rb
new file mode 100644
index 000000000..e2f5a114e
--- /dev/null
+++ b/test/lib/mocha/mock_methods.rb
@@ -0,0 +1,122 @@
+require 'mocha/expectation'
+require 'mocha/metaclass'
+
+module Mocha
+ # Methods added to mock objects.
+ # These methods all return an expectation which can be further modified by methods on Mocha::Expectation.
+ module MockMethods
+
+ # :stopdoc:
+
+ attr_reader :stub_everything
+
+ def expectations
+ @expectations ||= []
+ end
+
+ # :startdoc:
+
+ # :call-seq: expects(method_name) -> expectation
+ # expects(method_names) -> last expectation
+ #
+ # 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.
+ # object = mock()
+ # object.expects(:method1)
+ # object.method1
+ # # no error raised
+ #
+ # object = mock()
+ # object.expects(:method1)
+ # # error raised, because method1 not called exactly once
+ # If +method_names+ is a +Hash+, an expectation will be set up for each entry using the key as +method_name+ and value as +return_value+.
+ # object = mock()
+ # object.expects(:method1 => :result1, :method2 => :result2)
+ #
+ # # exactly equivalent to
+ #
+ # object = mock()
+ # object.expects(:method1).returns(:result1)
+ # object.expects(:method2).returns(:result2)
+ def expects(method_names, backtrace = nil)
+ method_names = method_names.is_a?(Hash) ? method_names : { method_names => nil }
+ method_names.each do |method_name, return_value|
+ expectations << Expectation.new(self, method_name, backtrace).returns(return_value)
+ self.__metaclass__.send(:undef_method, method_name) if self.__metaclass__.method_defined?(method_name)
+ end
+ expectations.last
+ end
+
+ alias_method :__expects__, :expects
+
+ # :call-seq: stubs(method_name) -> expectation
+ # stubs(method_names) -> last expectation
+ #
+ # 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.
+ # object = mock()
+ # object.stubs(:method1)
+ # object.method1
+ # object.method1
+ # # no error raised
+ # If +method_names+ is a +Hash+, an expectation will be set up for each entry using the key as +method_name+ and value as +return_value+.
+ # object = mock()
+ # object.stubs(:method1 => :result1, :method2 => :result2)
+ #
+ # # exactly equivalent to
+ #
+ # object = mock()
+ # object.stubs(:method1).returns(:result1)
+ # object.stubs(:method2).returns(:result2)
+ def stubs(method_names, backtrace = nil)
+ method_names = method_names.is_a?(Hash) ? method_names : { method_names => nil }
+ method_names.each do |method_name, return_value|
+ expectations << Stub.new(self, method_name, backtrace).returns(return_value)
+ self.__metaclass__.send(:undef_method, method_name) if self.__metaclass__.method_defined?(method_name)
+ end
+ expectations.last
+ end
+
+ alias_method :__stubs__, :stubs
+
+ # :stopdoc:
+
+ def method_missing(symbol, *arguments, &block)
+ matching_expectation = matching_expectation(symbol, *arguments)
+ if matching_expectation then
+ matching_expectation.invoke(&block)
+ elsif stub_everything then
+ return
+ else
+ begin
+ super_method_missing(symbol, *arguments, &block)
+ rescue NoMethodError
+ unexpected_method_called(symbol, *arguments)
+ end
+ end
+ end
+
+ def respond_to?(symbol)
+ expectations.any? { |expectation| expectation.method_name == symbol }
+ end
+
+ def super_method_missing(symbol, *arguments, &block)
+ raise NoMethodError
+ end
+
+ def unexpected_method_called(symbol, *arguments)
+ MissingExpectation.new(self, symbol).with(*arguments).verify
+ end
+
+ def matching_expectation(symbol, *arguments)
+ expectations.reverse.detect { |expectation| expectation.match?(symbol, *arguments) }
+ end
+
+ def verify(&block)
+ expectations.each { |expectation| expectation.verify(&block) }
+ end
+
+ # :startdoc:
+
+ end
+end \ No newline at end of file
diff --git a/test/lib/mocha/object.rb b/test/lib/mocha/object.rb
new file mode 100644
index 000000000..7b1d6b83e
--- /dev/null
+++ b/test/lib/mocha/object.rb
@@ -0,0 +1,100 @@
+require 'mocha/mock'
+require 'mocha/instance_method'
+require 'mocha/class_method'
+require 'mocha/any_instance_method'
+
+# Methods added all Objects.
+class Object
+
+ def mocha # :nodoc:
+ @mocha ||= Mocha::Mock.new
+ end
+
+ def reset_mocha # :nodoc:
+ @mocha = nil
+ end
+
+ def stubba_method # :nodoc:
+ Mocha::InstanceMethod
+ end
+
+ def stubba_object # :nodoc:
+ self
+ end
+
+ # :call-seq: expects(symbol) -> expectation
+ #
+ # Adds an expectation that a method identified by +symbol+ must be called exactly once with any parameters.
+ # Returns the new expectation which can be further modified by methods on Mocha::Expectation.
+ # product = Product.new
+ # product.expects(:save).returns(true)
+ # assert_equal false, product.save
+ def expects(symbol)
+ method = stubba_method.new(stubba_object, symbol)
+ $stubba.stub(method)
+ mocha.expects(symbol, caller)
+ end
+
+ # :call-seq: stubs(symbol) -> expectation
+ #
+ # Adds an expectation that a method identified by +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.
+ # product = Product.new
+ # product.stubs(:save).returns(true)
+ # assert_equal false, product.save
+ def stubs(symbol)
+ method = stubba_method.new(stubba_object, symbol)
+ $stubba.stub(method)
+ mocha.stubs(symbol, caller)
+ end
+
+ def verify # :nodoc:
+ mocha.verify
+ end
+
+end
+
+class Module # :nodoc:
+
+ def stubba_method
+ Mocha::ClassMethod
+ end
+
+end
+
+class Class
+
+ def stubba_method # :nodoc:
+ Mocha::ClassMethod
+ end
+
+ class AnyInstance # :nodoc:
+
+ def initialize(klass)
+ @stubba_object = klass
+ end
+
+ def stubba_method
+ Mocha::AnyInstanceMethod
+ end
+
+ def stubba_object
+ @stubba_object
+ end
+
+ end
+
+ # :call-seq: any_instance -> mock object
+ #
+ # Returns a mock object which will detect calls to any instance of this class.
+ # Product.any_instance.stubs(:save).returns(false)
+ # product_1 = Product.new
+ # assert_equal false, product_1.save
+ # product_2 = Product.new
+ # assert_equal false, product_2.save
+ def any_instance
+ @any_instance ||= AnyInstance.new(self)
+ end
+
+end
+
diff --git a/test/lib/mocha/pretty_parameters.rb b/test/lib/mocha/pretty_parameters.rb
new file mode 100644
index 000000000..6d3c165f8
--- /dev/null
+++ b/test/lib/mocha/pretty_parameters.rb
@@ -0,0 +1,28 @@
+require 'mocha/inspect'
+
+module Mocha
+
+ class PrettyParameters
+
+ def initialize(params)
+ @params = params
+ @params_string = params.mocha_inspect
+ end
+
+ def pretty
+ remove_outer_array_braces!
+ remove_outer_hash_braces!
+ @params_string
+ end
+
+ def remove_outer_array_braces!
+ @params_string = @params_string.gsub(/^\[|\]$/, '')
+ end
+
+ def remove_outer_hash_braces!
+ @params_string = @params_string.gsub(/^\{|\}$/, '') if @params.size == 1
+ end
+
+ end
+
+end \ No newline at end of file
diff --git a/test/lib/mocha/setup_and_teardown.rb b/test/lib/mocha/setup_and_teardown.rb
new file mode 100644
index 000000000..034ce1d6b
--- /dev/null
+++ b/test/lib/mocha/setup_and_teardown.rb
@@ -0,0 +1,23 @@
+require 'mocha/central'
+
+module Mocha
+
+ module SetupAndTeardown
+
+ def setup_stubs
+ $stubba = Mocha::Central.new
+ end
+
+ def verify_stubs
+ $stubba.verify_all { yield if block_given? } if $stubba
+ end
+
+ def teardown_stubs
+ if $stubba then
+ $stubba.unstub_all
+ $stubba = nil
+ end
+ end
+
+ end
+end \ No newline at end of file
diff --git a/test/lib/mocha/standalone.rb b/test/lib/mocha/standalone.rb
new file mode 100644
index 000000000..127ede641
--- /dev/null
+++ b/test/lib/mocha/standalone.rb
@@ -0,0 +1,30 @@
+require 'mocha/auto_verify'
+require 'mocha/setup_and_teardown'
+
+module Mocha
+
+ module Standalone
+
+ include AutoVerify
+ include SetupAndTeardown
+
+ def mocha_setup
+ setup_stubs
+ end
+
+ def mocha_verify(&block)
+ verify_mocks(&block)
+ verify_stubs(&block)
+ end
+
+ def mocha_teardown
+ begin
+ teardown_mocks
+ ensure
+ teardown_stubs
+ end
+ end
+
+ end
+
+end \ No newline at end of file
diff --git a/test/lib/mocha/test_case_adapter.rb b/test/lib/mocha/test_case_adapter.rb
new file mode 100644
index 000000000..dc7e33b68
--- /dev/null
+++ b/test/lib/mocha/test_case_adapter.rb
@@ -0,0 +1,49 @@
+require 'mocha/expectation_error'
+
+module Mocha
+
+ module TestCaseAdapter
+
+ def self.included(base)
+ base.class_eval do
+
+ alias_method :run_before_mocha_test_case_adapter, :run
+
+ def run(result)
+ yield(Test::Unit::TestCase::STARTED, name)
+ @_result = result
+ begin
+ mocha_setup
+ begin
+ setup
+ __send__(@method_name)
+ mocha_verify { add_assertion }
+ rescue Mocha::ExpectationError => e
+ add_failure(e.message, e.backtrace)
+ rescue Test::Unit::AssertionFailedError => e
+ add_failure(e.message, e.backtrace)
+ rescue StandardError, ScriptError
+ add_error($!)
+ ensure
+ begin
+ teardown
+ rescue Test::Unit::AssertionFailedError => e
+ add_failure(e.message, e.backtrace)
+ rescue StandardError, ScriptError
+ add_error($!)
+ end
+ end
+ ensure
+ mocha_teardown
+ end
+ result.add_run
+ yield(Test::Unit::TestCase::FINISHED, name)
+ end
+
+ end
+
+ end
+
+ end
+
+end \ No newline at end of file
diff --git a/test/lib/mocha_standalone.rb b/test/lib/mocha_standalone.rb
new file mode 100644
index 000000000..ce605811a
--- /dev/null
+++ b/test/lib/mocha_standalone.rb
@@ -0,0 +1,2 @@
+require 'mocha/standalone'
+require 'mocha/object'
diff --git a/test/lib/stubba.rb b/test/lib/stubba.rb
new file mode 100644
index 000000000..eade747f6
--- /dev/null
+++ b/test/lib/stubba.rb
@@ -0,0 +1,2 @@
+# for backwards compatibility
+require 'mocha' \ No newline at end of file
diff --git a/test/ral/providers/package/apt.rb b/test/ral/providers/package/apt.rb
new file mode 100644
index 000000000..f0a13d3aa
--- /dev/null
+++ b/test/ral/providers/package/apt.rb
@@ -0,0 +1,68 @@
+require File.dirname(__FILE__) + '/../../../lib/puppettest'
+
+require 'mocha'
+
+class AptPackageProviderTest < Test::Unit::TestCase
+ def setup
+ @type = Puppet::Type.type(:package)
+ # This is hideous, but absent a 'reset' button on types...
+ @type.instance_eval("@objects = {}")
+ end
+
+ def test_install
+ pkg = @type.create :name => 'faff',
+ :provider => :apt,
+ :ensure => :present,
+ :source => "/tmp/faff.deb"
+
+ pkg.provider.expects(
+ :dpkgquery
+ ).with(
+ '-W',
+ '--showformat',
+ '${Status} ${Package} ${Version}\n',
+ 'faff'
+ ).returns(
+ "deinstall ok config-files faff 1.2.3-1\n"
+ )
+
+ pkg.provider.expects(
+ :aptget
+ ).with(
+ '-q',
+ '-y',
+ '-o',
+ 'DPkg::Options::=--force-confold',
+ 'install',
+ 'faff'
+ ).returns(0)
+
+ pkg.evaluate.each { |state| state.transaction = self; state.forward }
+ end
+
+ def test_purge
+ pkg = @type.create :name => 'faff', :provider => :apt, :ensure => :purged
+
+ pkg.provider.expects(
+ :dpkgquery
+ ).with(
+ '-W',
+ '--showformat',
+ '${Status} ${Package} ${Version}\n',
+ 'faff'
+ ).returns(
+ "install ok installed faff 1.2.3-1\n"
+ )
+ pkg.provider.expects(
+ :aptget
+ ).with(
+ '-y',
+ '-q',
+ 'remove',
+ '--purge',
+ 'faff'
+ ).returns(0)
+
+ pkg.evaluate.each { |state| state.transaction = self; state.forward }
+ end
+end
diff --git a/test/ral/providers/package/aptitude.rb b/test/ral/providers/package/aptitude.rb
new file mode 100644
index 000000000..0a686559e
--- /dev/null
+++ b/test/ral/providers/package/aptitude.rb
@@ -0,0 +1,65 @@
+require File.dirname(__FILE__) + '/../../../lib/puppettest'
+
+require 'mocha'
+
+class AptitudePackageProviderTest < Test::Unit::TestCase
+ def setup
+ @type = Puppet::Type.type(:package)
+ # This is hideous, but absent a 'reset' button on types...
+ @type.instance_eval("@objects = {}")
+ end
+
+ def test_install
+ pkg = @type.create :name => 'faff',
+ :provider => :aptitude,
+ :ensure => :present,
+ :source => "/tmp/faff.deb"
+
+ pkg.provider.expects(
+ :dpkgquery
+ ).with(
+ '-W',
+ '--showformat',
+ '${Status} ${Package} ${Version}\n',
+ 'faff'
+ ).returns(
+ "deinstall ok config-files faff 1.2.3-1\n"
+ )
+
+ pkg.provider.expects(
+ :aptitude
+ ).with(
+ '-y',
+ '-o',
+ 'DPkg::Options::=--force-confold',
+ 'install',
+ 'faff'
+ ).returns(0)
+
+ pkg.evaluate.each { |state| state.transaction = self; state.forward }
+ end
+
+ def test_purge
+ pkg = @type.create :name => 'faff', :provider => :aptitude, :ensure => :purged
+
+ pkg.provider.expects(
+ :dpkgquery
+ ).with(
+ '-W',
+ '--showformat',
+ '${Status} ${Package} ${Version}\n',
+ 'faff'
+ ).returns(
+ "install ok installed faff 1.2.3-1\n"
+ )
+ pkg.provider.expects(
+ :aptitude
+ ).with(
+ '-y',
+ 'purge',
+ 'faff'
+ ).returns(0)
+
+ pkg.evaluate.each { |state| state.transaction = self; state.forward }
+ end
+end
diff --git a/test/ral/providers/package/dpkg.rb b/test/ral/providers/package/dpkg.rb
new file mode 100644
index 000000000..2557dd073
--- /dev/null
+++ b/test/ral/providers/package/dpkg.rb
@@ -0,0 +1,61 @@
+require File.dirname(__FILE__) + '/../../../lib/puppettest'
+
+require 'mocha'
+
+class DpkgPackageProviderTest < Test::Unit::TestCase
+ def setup
+ @type = Puppet::Type.type(:package)
+ # This is hideous, but absent a 'reset' button on types...
+ @type.instance_eval("@objects = {}")
+ end
+
+ def test_install
+ pkg = @type.create :name => 'faff',
+ :provider => :dpkg,
+ :ensure => :present,
+ :source => "/tmp/faff.deb"
+
+ pkg.provider.expects(
+ :dpkgquery
+ ).with(
+ '-W',
+ '--showformat',
+ '${Status} ${Package} ${Version}\n',
+ 'faff'
+ ).returns(
+ "deinstall ok config-files faff 1.2.3-1\n"
+ )
+
+ pkg.provider.expects(
+ :dpkg
+ ).with(
+ '-i',
+ '/tmp/faff.deb'
+ ).returns(0)
+
+ pkg.evaluate.each { |state| state.transaction = self; state.forward }
+ end
+
+ def test_purge
+ pkg = @type.create :name => 'faff', :provider => :dpkg, :ensure => :purged
+
+ pkg.provider.expects(
+ :dpkgquery
+ ).with(
+ '-W',
+ '--showformat',
+ '${Status} ${Package} ${Version}\n',
+ 'faff'
+ ).returns(
+ "install ok installed faff 1.2.3-1\n"
+ )
+ pkg.provider.expects(
+ :dpkg
+ ).with(
+ '--purge',
+ 'faff'
+ ).returns(0)
+
+ pkg.evaluate.each { |state| state.transaction = self; state.forward }
+ end
+end