class Mock
Represents a mock object that can intercept and replace method calls on a target object.
Definitions
def initialize(target)
Initialize a new mock for the given target.
Signature
-
parameter
targetObject The object to mock.
Implementation
def initialize(target)
@target = target
@interceptor = Module.new
@target.singleton_class.prepend(@interceptor)
end
attr :target
Signature
-
attribute
Object The target object being mocked.
def print(output)
Print a representation of this mock.
Signature
-
parameter
outputOutput The output target.
Implementation
def print(output)
output.write("mock ", :context, @target.inspect)
end
def clear
Clear all mocked methods from the target.
Implementation
def clear
@interceptor.instance_methods.each do |method_name|
@interceptor.remove_method(method_name)
end
end
def replace(method, &hook)
Replace a method implementation.
Signature
-
parameter
methodSymbol The method name to replace.
-
yields
{|*arguments, **options, &block| ...} The replacement implementation.
-
returns
Mock Returns self for method chaining.
Implementation
def replace(method, &hook)
execution_context = Thread.current
@interceptor.define_method(method) do |*arguments, **options, &block|
if execution_context == Thread.current
hook.call(*arguments, **options, &block)
else
super(*arguments, **options, &block)
end
end
return self
end
def before(method, &hook)
Add a hook that runs before a method is called.
Signature
-
parameter
methodSymbol The method name to hook.
-
yields
{|*arguments, **options, &block| ...} The hook to execute before the method.
-
returns
Mock Returns self for method chaining.
Implementation
def before(method, &hook)
execution_context = Thread.current
@interceptor.define_method(method) do |*arguments, **options, &block|
hook.call(*arguments, **options, &block) if execution_context == Thread.current
super(*arguments, **options, &block)
end
return self
end
def after(method, &hook)
Add a hook that runs after a method is called.
Signature
-
parameter
methodSymbol The method name to hook.
-
yields
{|result, *arguments, **options, &block| ...} The hook to execute after the method, receiving the result as the first argument.
-
returns
Mock Returns self for method chaining.
Implementation
def after(method, &hook)
execution_context = Thread.current
@interceptor.define_method(method) do |*arguments, **options, &block|
result = super(*arguments, **options, &block)
hook.call(result, *arguments, **options, &block) if execution_context == Thread.current
return result
end
return self
end
def wrap(method, &hook)
Wrap a method, yielding the original method as the first argument, so you can call it from within the hook.
Signature
-
parameter
methodSymbol The method name to wrap.
-
yields
{|original, *arguments, **options, &block| ...} The wrapper implementation, receiving the original method as the first argument.
Implementation
def wrap(method, &hook)
execution_context = Thread.current
@interceptor.define_method(method) do |*arguments, **options, &block|
if execution_context == Thread.current
original = proc do |*arguments, **options, &block|
super(*arguments, **options, &block)
end
hook.call(original, *arguments, **options, &block)
else
super(*arguments, **options, &block)
end
end
end