mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Some initial work on mocks
This commit is contained in:
parent
e035afa85f
commit
42aaae7908
2 changed files with 107 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
||||||
require "../double"
|
require "../double"
|
||||||
require "../generic_method_stub"
|
require "../generic_method_stub"
|
||||||
require "../open_mock"
|
require "../open_mock"
|
||||||
|
require "../stubs"
|
||||||
|
|
||||||
module Spectator::DSL
|
module Spectator::DSL
|
||||||
macro double(name, &block)
|
macro double(name, &block)
|
||||||
|
@ -19,6 +20,30 @@ module Spectator::DSL
|
||||||
{% end %}
|
{% end %}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
macro mock(name, &block)
|
||||||
|
{% if block.is_a?(Nop) %}
|
||||||
|
{{name}}.new.tap do |%inst|
|
||||||
|
%inst.spectator_test = self
|
||||||
|
end
|
||||||
|
{% else %}
|
||||||
|
{% resolved = name.resolve
|
||||||
|
type = if resolved < Reference
|
||||||
|
:class
|
||||||
|
elsif resolved < Value
|
||||||
|
:struct
|
||||||
|
else
|
||||||
|
:module
|
||||||
|
end
|
||||||
|
%}
|
||||||
|
{{type.id}} ::{{resolved.id}}
|
||||||
|
include ::Spectator::Stubs
|
||||||
|
|
||||||
|
{{block.body}}
|
||||||
|
end
|
||||||
|
{% end %}
|
||||||
|
{% debug %}
|
||||||
|
end
|
||||||
|
|
||||||
def allow(double : ::Spectator::Double)
|
def allow(double : ::Spectator::Double)
|
||||||
OpenMock.new(double)
|
OpenMock.new(double)
|
||||||
end
|
end
|
||||||
|
|
82
src/spectator/stubs.cr
Normal file
82
src/spectator/stubs.cr
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
module Spectator
|
||||||
|
module Stubs
|
||||||
|
private macro stub(definition, &block)
|
||||||
|
{%
|
||||||
|
name = nil
|
||||||
|
params = nil
|
||||||
|
args = nil
|
||||||
|
body = nil
|
||||||
|
if definition.is_a?(Call) # stub foo { :bar }
|
||||||
|
name = definition.name.id
|
||||||
|
params = definition.args
|
||||||
|
args = params.map { |p| p.is_a?(TypeDeclaration) ? p.var : p.id }
|
||||||
|
body = definition.block.is_a?(Nop) ? block : definition.block
|
||||||
|
elsif definition.is_a?(TypeDeclaration) # stub foo : Symbol
|
||||||
|
name = definition.var
|
||||||
|
params = [] of MacroId
|
||||||
|
args = [] of MacroId
|
||||||
|
body = block
|
||||||
|
else
|
||||||
|
raise "Unrecognized stub format"
|
||||||
|
end
|
||||||
|
%}
|
||||||
|
def {{name}}{% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %}
|
||||||
|
%method
|
||||||
|
end
|
||||||
|
|
||||||
|
{% if name.ends_with?('=') && name.id != "[]=" %}
|
||||||
|
def {{name}}(arg)
|
||||||
|
call = ::Spectator::GenericMethodCall.new({{name.symbolize}}, {arg}, NamedTuple.new)
|
||||||
|
@spectator_stub_calls << call
|
||||||
|
stub = @spectator_stubs.find(&.callable?(call))
|
||||||
|
if stub
|
||||||
|
stub.as(::Spectator::GenericMethodStub(typeof(%method(arg)))).call(call)
|
||||||
|
else
|
||||||
|
%method(arg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
{% else %}
|
||||||
|
def {{name}}(*args, **options){% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %}
|
||||||
|
call = ::Spectator::GenericMethodCall.new({{name.symbolize}}, args, options)
|
||||||
|
@spectator_stub_calls << call
|
||||||
|
stub = @spectator_stubs.find(&.callable?(call))
|
||||||
|
if stub
|
||||||
|
stub.as(::Spectator::GenericMethodStub(typeof(%method(*args, **options)))).call(call)
|
||||||
|
else
|
||||||
|
%method(*args, **options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
{% if name != "[]=" %}
|
||||||
|
def {{name}}(*args, **options){% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %}
|
||||||
|
call = ::Spectator::GenericMethodCall.new({{name.symbolize}}, args, options)
|
||||||
|
@spectator_stub_calls << call
|
||||||
|
stub = @spectator_stubs.find(&.callable?(call))
|
||||||
|
if stub
|
||||||
|
stub.as(::Spectator::GenericMethodStub(typeof(%method(*args, **options) { |*yield_args| yield *yield_args }))).call(call)
|
||||||
|
else
|
||||||
|
%method(*args, **options) do |*yield_args|
|
||||||
|
yield *yield_args
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
{% end %}
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
def %method({{params.splat}}){% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %}
|
||||||
|
{% if body && !body.is_a?(Nop) %}
|
||||||
|
{{body.body}}
|
||||||
|
{% else %}
|
||||||
|
raise "Stubbed method called without being allowed"
|
||||||
|
# This code shouldn't be reached, but makes the compiler happy to have a matching type.
|
||||||
|
{% if definition.is_a?(TypeDeclaration) %}
|
||||||
|
%x = uninitialized {{definition.type}}
|
||||||
|
{% else %}
|
||||||
|
nil
|
||||||
|
{% end %}
|
||||||
|
{% end %}
|
||||||
|
end
|
||||||
|
{% debug %}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue