Implement allow_any_instance_of

This commit is contained in:
Michael Miller 2019-11-10 09:46:23 -07:00
parent f816a64770
commit a2b72eaa36
3 changed files with 38 additions and 5 deletions

View file

@ -39,6 +39,10 @@ module Spectator::DSL
Mocks::Allow.new(thing)
end
def allow_any_instance_of(type : T.class) forall T
Mocks::AllowAnyInstance(T).new
end
macro receive(method_name, _source_file = __FILE__, _source_line = __LINE__)
%source = ::Spectator::Source.new({{_source_file}}, {{_source_line}})
::Spectator::Mocks::NilMethodStub.new({{method_name.symbolize}}, %source)

View file

@ -0,0 +1,9 @@
require "./registry"
module Spectator::Mocks
struct AllowAnyInstance(T)
def to(stub : MethodStub) : Nil
Harness.current.mocks.add_type_stub(T, stub)
end
end
end

View file

@ -7,6 +7,7 @@ module Spectator::Mocks
getter calls = Deque(MethodCall).new
end
@all_instances = {} of String => Entry
@entries = {} of Key => Entry
def prepare(context : TestContext) : Nil
@ -20,22 +21,32 @@ module Spectator::Mocks
def add_stub(object, stub : MethodStub) : Nil
# Stubs are added in reverse order,
# so that later-defined stubs override previously defined ones.
fetch(object).stubs.unshift(stub)
fetch_instance(object).stubs.unshift(stub)
end
def add_type_stub(type, stub : MethodStub) : Nil
fetch_type(type).stubs.unshift(stub)
end
def find_stub(object, call : GenericMethodCall(T, NT)) forall T, NT
fetch(object).stubs.find(&.callable?(call))
fetch_instance(object).stubs.find(&.callable?(call)) ||
fetch_type(object.class).stubs.find(&.callable?(call))
end
def record_call(object, call : MethodCall) : Nil
fetch(object).calls << call
fetch_instance(object).calls << call
fetch_type(object.class).calls << call
end
def calls_for(object, method_name : Symbol)
fetch(object).calls.select { |call| call.name == method_name }
fetch_instance(object).calls.select { |call| call.name == method_name }
end
private def fetch(object)
def calls_for_type(type, method_name : Symbol)
fetch_type(type).calls.select { |call| call.name == method_name }
end
private def fetch_instance(object)
key = unique_key(object)
if @entries.has_key?(key)
@entries[key]
@ -44,6 +55,15 @@ module Spectator::Mocks
end
end
private def fetch_type(type)
key = type.name
if @all_instances.has_key?(key)
@all_instances[key]
else
@all_instances[key] = Entry.new
end
end
private def unique_key(reference : Reference)
{reference.class.name, reference.object_id}
end