mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Merge remote-tracking branch 'origin/master' into release/0.10
This commit is contained in:
commit
6c55301d0b
11 changed files with 140 additions and 12 deletions
|
@ -98,6 +98,7 @@ module Spectator
|
|||
elapsed = Time.measure do
|
||||
error = catch { yield }
|
||||
end
|
||||
error = nil if error.is_a?(SystemExit) && mocks.exit_handled?
|
||||
{elapsed, error}
|
||||
end
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
require "./mocks/*"
|
||||
require "./system_exit"
|
||||
|
||||
module Spectator
|
||||
# Functionality for mocking existing types.
|
||||
|
@ -11,3 +12,13 @@ module Spectator
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Add default stub to `exit` method.
|
||||
# This captures *most* (technically not all) attempts to exit the process.
|
||||
# This stub only takes effect in example code.
|
||||
# It intercepts `exit` calls and raises `Spectator::SystemExit` to prevent killing the test.
|
||||
class ::Process
|
||||
include ::Spectator::Mocks::Stubs
|
||||
|
||||
stub self.exit(code) { raise ::Spectator::SystemExit.new }
|
||||
end
|
||||
|
|
|
@ -20,6 +20,8 @@ module Spectator::Mocks
|
|||
value = call(args) { |*ya| yield *ya }
|
||||
if value.is_a?(RT)
|
||||
value.as(RT)
|
||||
elsif value.nil? && RT == NoReturn
|
||||
raise SystemExit.new
|
||||
else
|
||||
raise TypeCastError.new("The return type of stub #{self} doesn't match the expected type #{RT}")
|
||||
end
|
||||
|
|
|
@ -41,6 +41,10 @@ module Spectator::Mocks
|
|||
NilMethodStub.new(@name, @location, args)
|
||||
end
|
||||
|
||||
def with(args : Arguments)
|
||||
NilMethodStub.new(@name, @location, @args)
|
||||
end
|
||||
|
||||
def and_call_original
|
||||
OriginalMethodStub.new(@name, @location, @args)
|
||||
end
|
||||
|
|
|
@ -35,6 +35,10 @@ module Spectator::Mocks
|
|||
fetch_type(object.class).stubs.find(&.callable?(call))
|
||||
end
|
||||
|
||||
def find_stub(type : T.class, call : MethodCall) forall T
|
||||
fetch_type(type).stubs.find(&.callable?(call))
|
||||
end
|
||||
|
||||
def record_call(object, call : MethodCall) : Nil
|
||||
fetch_instance(object).calls << call
|
||||
fetch_type(object.class).calls << call
|
||||
|
@ -53,6 +57,14 @@ module Spectator::Mocks
|
|||
fetch_type(object.class).expected.any?(&.callable?(call))
|
||||
end
|
||||
|
||||
def exit_handled? : Bool
|
||||
# Lazily check if an `exit` method was called and it was expected.
|
||||
# This is okay since an `expect().to receive(:exit)` should check the details of the call.
|
||||
(@entries.any? { |_key, entry| entry.expected.any? { |stub| stub.name == :exit } } ||
|
||||
@all_instances.any? { |_key, entry| entry.expected.any? { |stub| stub.name == :exit } }) &&
|
||||
@entries.any? { |_key, entry| entry.calls.any? { |call| call.name == :exit } }
|
||||
end
|
||||
|
||||
def expect(object, stub : MethodStub) : Nil
|
||||
entry = fetch_instance(object)
|
||||
entry.expected.add(stub)
|
||||
|
|
|
@ -62,7 +62,7 @@ module Spectator::Mocks
|
|||
elsif t.has_method?(name)
|
||||
:previous_def
|
||||
else
|
||||
"::#{name}"
|
||||
name
|
||||
end.id
|
||||
%}
|
||||
|
||||
|
@ -82,11 +82,7 @@ module Spectator::Mocks
|
|||
%call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args)
|
||||
%harness.mocks.record_call(self, %call)
|
||||
if (%stub = %harness.mocks.find_stub(self, %call))
|
||||
if typeof({{original}}) == NoReturn
|
||||
return %stub.call!(%args) { nil }
|
||||
else
|
||||
return %stub.call!(%args) { {{original}} }
|
||||
end
|
||||
return %stub.call!(%args) { {{original}} }
|
||||
end
|
||||
|
||||
{% if body && !body.is_a?(Nop) || return_type.is_a?(ArrayLiteral) %}
|
||||
|
@ -105,11 +101,7 @@ module Spectator::Mocks
|
|||
%call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args)
|
||||
%harness.mocks.record_call(self, %call)
|
||||
if (%stub = %harness.mocks.find_stub(self, %call))
|
||||
if typeof({{original}}) == NoReturn
|
||||
return %stub.call!(%args) { nil }
|
||||
else
|
||||
return %stub.call!(%args) { {{original}} { |*%ya| yield *%ya } }
|
||||
end
|
||||
return %stub.call!(%args) { {{original}} { |*%ya| yield *%ya } }
|
||||
end
|
||||
|
||||
{% if body && !body.is_a?(Nop) || return_type.is_a?(ArrayLiteral) %}
|
||||
|
|
5
src/spectator/system_exit.cr
Normal file
5
src/spectator/system_exit.cr
Normal file
|
@ -0,0 +1,5 @@
|
|||
module Spectator
|
||||
# Exception raised when `exit` is called and intercepted from a stub.
|
||||
class SystemExit < Exception
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue