Use TypedStub instead of ValueStub

Test possible issues around stub returning nil
This commit is contained in:
Michael Miller 2022-03-16 21:07:20 -06:00
parent 8e38d3b054
commit 280f117e23
No known key found for this signature in database
GPG key ID: AC78B32D30CE34A2
3 changed files with 64 additions and 7 deletions

View file

@ -50,6 +50,24 @@ Spectator.describe Spectator::Double do
end
end
context "with nillable return type annotations" do
Spectator::Double.define(TestDouble) do
abstract_stub abstract def foo : String?
abstract_stub abstract def bar : Nil
end
let(foo_stub) { Spectator::ValueStub.new(:foo, nil).as(Spectator::Stub) }
let(bar_stub) { Spectator::ValueStub.new(:bar, nil).as(Spectator::Stub) }
subject(dbl) { TestDouble.new([foo_stub, bar_stub]) }
it "doesn't raise on nil" do
aggregate_failures do
expect(dbl.foo).to be_nil
expect(dbl.bar).to be_nil
end
end
end
context "with common object methods" do
subject(dbl) do
EmptyDouble.new([

View file

@ -58,6 +58,24 @@ Spectator.describe Spectator::NullDouble do
end
end
context "with nillable return type annotations" do
Spectator::NullDouble.define(TestDouble) do
abstract_stub abstract def foo : String?
abstract_stub abstract def bar : Nil
end
let(foo_stub) { Spectator::ValueStub.new(:foo, nil).as(Spectator::Stub) }
let(bar_stub) { Spectator::ValueStub.new(:bar, nil).as(Spectator::Stub) }
subject(dbl) { TestDouble.new([foo_stub, bar_stub]) }
it "doesn't raise on nil" do
aggregate_failures do
expect(dbl.foo).to be_nil
expect(dbl.bar).to be_nil
end
end
end
context "with common object methods" do
subject(dbl) do
EmptyDouble.new([

View file

@ -52,6 +52,9 @@ module Spectator
# This method can also raise an error if it's impossible to return something.
abstract def _spectator_abstract_stub_fallback(call : MethodCall, type)
# Utility method returning the stubbed type's name formatted for user output.
abstract def _spectator_stubbed_name : String
# Redefines a method to accept stubs.
#
# The *method* should be a `Def`.
@ -101,12 +104,21 @@ module Spectator
if %stub = _spectator_find_stub(%call)
{% if !method.abstract? %}
%stub.as(::Spectator::ValueStub(typeof({{original}}))).value
%stub.as(::Spectator::TypedStub(typeof({{original}}))).value
{% elsif method.return_type %}
if %cast = %stub.as?(::Spectator::ValueStub({{method.return_type}}))
%cast.value
if %typed = %stub.as?(::Spectator::TypedStub({{method.return_type}}))
%typed.value
else
%stub.value.as({{method.return_type}})
%value = %stub.value
if %cast = %value.as?({{method.return_type}})
%cast
else
{% if method.return_type.resolve >= Nil %}
nil
{% else %}
raise TypeCastError.new("#{_spectator_stubbed_name} received message #{%call} and is attempting to return a `#{%value.class}`, but returned type must be `{{method.return_type}}`.")
{% end %}
end
end
{% else %}
%stub.value
@ -165,10 +177,19 @@ module Spectator
if %stub = _spectator_find_stub(%call)
{% if method.return_type %}
if %cast = %stub.as?(::Spectator::ValueStub({{method.return_type}}))
%cast.value
if %typed = %stub.as?(::Spectator::TypedStub({{method.return_type}}))
%typed.value
else
%stub.value.as({{method.return_type}})
%value = %stub.value
if %cast = %value.as?({{method.return_type}})
%cast
else
{% if method.return_type.resolve >= Nil %}
nil
{% else %}
raise TypeCastError.new("#{_spectator_stubbed_name} received message #{%call} and is attempting to return a `#{%value.class}`, but returned type must be `{{method.return_type}}`.")
{% end %}
end
end
{% else %}
%stub.value