Class: MiniTest::Mock

Inherits:
Object show all
Defined in:
lib/minitest/mock.rb

Overview

All mock objects are an instance of Mock

Instance Method Summary collapse

Constructor Details

#initializeMock

:nodoc:



21
22
23
24
# File 'lib/minitest/mock.rb', line 21

def initialize # :nodoc:
  @expected_calls = Hash.new { |calls, name| calls[name] = [] }
  @actual_calls   = Hash.new { |calls, name| calls[name] = [] }
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args) ⇒ Object

:nodoc:



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/minitest/mock.rb', line 75

def method_missing(sym, *args) # :nodoc:
  unless @expected_calls.has_key?(sym) then
    raise NoMethodError, "unmocked method %p, expected one of %p" %
      [sym, @expected_calls.keys.sort_by(&:to_s)]
  end

  expected_calls = @expected_calls[sym].select { |call| call[:args].size == args.size }

  if expected_calls.empty?
    arg_sizes = @expected_calls[sym].map { |call| call[:args].size }.uniq.sort
    raise ArgumentError, "mocked method %p expects %s arguments, got %d" %
      [sym, arg_sizes.join('/'), args.size]
  end

  expected_call = expected_calls.find do |call|
    call[:args].zip(args).all? { |mod, a| mod === a or mod == a }
  end

  unless expected_call
    raise MockExpectationError, "mocked method %p called with unexpected arguments %p" %
      [sym, args]
  end

  expected_args, retval = expected_call[:args], expected_call[:retval]
  
  @actual_calls[sym] << {
    :retval => retval,
    :args => expected_args.zip(args).map { |mod, a| mod === a ? mod : a }
  }

  retval
end

Instance Method Details

#__respond_to?Object



13
# File 'lib/minitest/mock.rb', line 13

alias :__respond_to? :respond_to?

#expect(name, retval, args = []) ⇒ Object

Expect that method name is called, optionally with args, and returns retval.

@mock.expect(:meaning_of_life, 42)
@mock.meaning_of_life # => 42

@mock.expect(:do_something_with, true, [some_obj, true])
@mock.do_something_with(some_obj, true) # => true

args is compared to the expected args using case equality (ie, the ‘===’ operator), allowing for less specific expectations.

@mock.expect(:uses_any_string, true, [String])
@mock.uses_any_string("foo") # => true
@mock.verify  # => true

@mock.expect(:uses_one_string, true, ["foo"]
@mock.uses_one_string("bar") # => true
@mock.verify  # => raises MockExpectationError

Raises:

  • (ArgumentError)


47
48
49
50
51
# File 'lib/minitest/mock.rb', line 47

def expect(name, retval, args=[])
  raise ArgumentError, "args must be an array" unless Array === args
  @expected_calls[name] << { :retval => retval, :args => args }
  self
end

#respond_to?(sym) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


108
109
110
111
# File 'lib/minitest/mock.rb', line 108

def respond_to?(sym) # :nodoc:
  return true if @expected_calls.has_key?(sym.to_sym)
  return __respond_to?(sym)
end

#verifyObject

Verify that all methods were called as expected. Raises MockExpectationError if the mock object was not called as expected.



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/minitest/mock.rb', line 58

def verify
  @expected_calls.each do |name, calls|
    calls.each do |expected|
      msg1 = "expected #{name}, #{expected.inspect}"
      msg2 = "#{msg1}, got #{@actual_calls[name].inspect}"

      raise MockExpectationError, msg2 if
        @actual_calls.has_key? name and
        not @actual_calls[name].include?(expected)

      raise MockExpectationError, msg1 unless
        @actual_calls.has_key? name and @actual_calls[name].include?(expected)
    end
  end
  true
end