diff options
| -rw-r--r-- | test/lib/mocha.rb | 19 | ||||
| -rw-r--r-- | test/lib/mocha/any_instance_method.rb | 35 | ||||
| -rw-r--r-- | test/lib/mocha/auto_verify.rb | 113 | ||||
| -rw-r--r-- | test/lib/mocha/central.rb | 35 | ||||
| -rw-r--r-- | test/lib/mocha/class_method.rb | 62 | ||||
| -rw-r--r-- | test/lib/mocha/expectation.rb | 295 | ||||
| -rw-r--r-- | test/lib/mocha/expectation_error.rb | 6 | ||||
| -rw-r--r-- | test/lib/mocha/infinite_range.rb | 27 | ||||
| -rw-r--r-- | test/lib/mocha/inspect.rb | 37 | ||||
| -rw-r--r-- | test/lib/mocha/instance_method.rb | 8 | ||||
| -rw-r--r-- | test/lib/mocha/metaclass.rb | 7 | ||||
| -rw-r--r-- | test/lib/mocha/mock.rb | 20 | ||||
| -rw-r--r-- | test/lib/mocha/mock_methods.rb | 122 | ||||
| -rw-r--r-- | test/lib/mocha/object.rb | 100 | ||||
| -rw-r--r-- | test/lib/mocha/pretty_parameters.rb | 28 | ||||
| -rw-r--r-- | test/lib/mocha/setup_and_teardown.rb | 23 | ||||
| -rw-r--r-- | test/lib/mocha/standalone.rb | 30 | ||||
| -rw-r--r-- | test/lib/mocha/test_case_adapter.rb | 49 | ||||
| -rw-r--r-- | test/lib/mocha_standalone.rb | 2 | ||||
| -rw-r--r-- | test/lib/stubba.rb | 2 | ||||
| -rw-r--r-- | test/ral/providers/package/apt.rb | 68 | ||||
| -rw-r--r-- | test/ral/providers/package/aptitude.rb | 65 | ||||
| -rw-r--r-- | test/ral/providers/package/dpkg.rb | 61 |
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, ¶meter_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, ¶meter_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 |
