module Spy::Mock

A Mock is an object that has all the same methods as the given class. Each method however will raise a NeverHookedError if it hasn't been stubbed. If you attempt to stub a method on the mock that doesn't exist on the original class it will raise an error.

Constants

CLASSES_NOT_TO_OVERRIDE
METHODS_NOT_TO_OVERRIDE

Public Class Methods

new(&mock_method) click to toggle source
# File lib/spy/mock.rb, line 11
def initialize(&mock_method)
  Agency.instance.recruit(self)
end
new(klass) click to toggle source

This will create a new Mock class with all the instance methods of given klass mocked out. @param klass [Class] @return [Class]

# File lib/spy/mock.rb, line 41
def new(klass)
  mock_klass = Class.new(klass)
  mock_klass.class_exec do
    alias :_mock_class :class
    private :_mock_class

    define_method(:class) do
      klass
    end

    include Mock
  end
  mock_klass
end

Private Class Methods

args_for_method(method) click to toggle source
# File lib/spy/mock.rb, line 102
def args_for_method(method)
  args = method.parameters
  args.map! do |type,name|
    name ||= :args
    case type
    when :req
      name
    when :opt
      "#{name} = nil"
    when :rest
      "*#{name}"
    end
  end
  args.compact!
  args << "&mock_method"
  args.join(",")
end
classes_to_override_methods(mod) click to toggle source
# File lib/spy/mock.rb, line 82
def classes_to_override_methods(mod)
  method_classes = mod.ancestors
  method_classes.shift
  method_classes.delete(self)
  CLASSES_NOT_TO_OVERRIDE.each do |klass|
    index = method_classes.index(klass)
    method_classes.slice!(index..-1) if index
  end
  method_classes
end
get_inherited_methods(klass_ancestors, visibility) click to toggle source
# File lib/spy/mock.rb, line 93
def get_inherited_methods(klass_ancestors, visibility)
  instance_methods = klass_ancestors.map do |klass|
    klass.send("#{visibility}_instance_methods".to_sym, false)
  end
  instance_methods.flatten!
  instance_methods.uniq!
  instance_methods - METHODS_NOT_TO_OVERRIDE
end
included(mod) click to toggle source
# File lib/spy/mock.rb, line 58
      def included(mod)
        method_classes = classes_to_override_methods(mod)

        mocked_methods = []
        [:public, :protected, :private].each do |visibility|
          get_inherited_methods(method_classes, visibility).each do |method_name|
            mocked_methods << method_name
            args = args_for_method(mod.instance_method(method_name))

            mod.class_eval <<-DEF_METHOD, __FILE__, __LINE__ + 1
              def #{method_name}(#{args})
                raise ::Spy::NeverHookedError, "'#{method_name}' was never hooked on mock spy."
              end
            DEF_METHOD

            mod.send(visibility, method_name)
          end
        end

        mod.define_singleton_method(:mocked_methods) do
          mocked_methods
        end
      end

Public Instance Methods

instance_of?(other) click to toggle source

the only method that doesn't work correctly of a mock if inherited. We overwite for compatibility. @param other [Class] @return [Boolean]

# File lib/spy/mock.rb, line 19
def instance_of?(other)
  other == self.class
end
method(method_name) click to toggle source

returns the original class method if the current method is a mock_method @param method_name [Symbol, String] @return [Method]

Calls superclass method
# File lib/spy/mock.rb, line 26
def method(method_name)
  new_method = super
  parameters = new_method.parameters
  if parameters.size >= 1 && parameters.last.last == :mock_method
    self.class.instance_method(method_name).bind(self)
  else
    new_method
  end
end