Use responds_to? to ensure stub is cast correctly

This commit is contained in:
Michael Miller 2022-03-31 22:39:21 -06:00
parent 9c1357da3f
commit 003be48591
No known key found for this signature in database
GPG key ID: 32B47AE8F388A1FF
3 changed files with 16 additions and 3 deletions

View file

@ -57,9 +57,13 @@ module Spectator
_spectator_cast_stub_value(%stub, %call, \{{Messages[{{call.name.symbolize}}.id]}}, \{{Messages[{{call.name.symbolize}}.id].resolve >= Nil}}) _spectator_cast_stub_value(%stub, %call, \{{Messages[{{call.name.symbolize}}.id]}}, \{{Messages[{{call.name.symbolize}}.id].resolve >= Nil}})
\{% else %} \{% else %}
# A method that was not defined during initialization was stubbed. # A method that was not defined during initialization was stubbed.
# Even though all stubs will have a #value method, the compiler doesn't seem to agree.
# Assert that it will (this should never fail).
raise TypeCastError.new("Stub has no value") unless %stub.responds_to?(:value)
# Return the value of the stub as-is. # Return the value of the stub as-is.
# Might want to give a warning here, as this may produce a "bloated" union of all known stub types. # Might want to give a warning here, as this may produce a "bloated" union of all known stub types.
%stub.as(::Spectator::ValueStub).value %stub.value
\{% end %} \{% end %}
else else
# A stub wasn't found, invoke the fallback logic. # A stub wasn't found, invoke the fallback logic.

View file

@ -60,9 +60,13 @@ module Spectator
# Attempt to find a stub that satisfies the method call and arguments. # Attempt to find a stub that satisfies the method call and arguments.
if %stub = _spectator_find_stub(%call) if %stub = _spectator_find_stub(%call)
# A method that was not defined during initialization was stubbed. # A method that was not defined during initialization was stubbed.
# Even though all stubs will have a #value method, the compiler doesn't seem to agree.
# Assert that it will (this should never fail).
raise TypeCastError.new("Stub has no value") unless %stub.responds_to?(:value)
# Return the value of the stub as-is. # Return the value of the stub as-is.
# Might want to give a warning here, as this may produce a "bloated" union of all known stub types. # Might want to give a warning here, as this may produce a "bloated" union of all known stub types.
%stub.as(::Spectator::ValueStub).value %stub.value
else else
# A stub wasn't found, invoke the fallback logic. # A stub wasn't found, invoke the fallback logic.
# Message received for a methods that isn't stubbed nor defined when initialized. # Message received for a methods that isn't stubbed nor defined when initialized.

View file

@ -276,9 +276,14 @@ module Spectator
%typed.value %typed.value
else else
# The stub couldn't be easily cast to match the return type. # The stub couldn't be easily cast to match the return type.
# Even though all stubs will have a #value method, the compiler doesn't seem to agree.
# Assert that it will (this should never fail).
raise TypeCastError.new("Stub has no value") unless {{stub}}.responds_to?(:value)
# Get the value as-is from the stub. # Get the value as-is from the stub.
# This will be compiled as a union of all known stubbed value types. # This will be compiled as a union of all known stubbed value types.
%value = {{stub}}.as(::Spectator::ValueStub).value %value = {{stub}}.value
# Attempt to cast the value to the method's return type. # Attempt to cast the value to the method's return type.
# If successful, which it will be in most cases, return it. # If successful, which it will be in most cases, return it.