mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Support free variables in mocked types
This commit is contained in:
parent
2985ef5919
commit
293faccd5c
3 changed files with 56 additions and 4 deletions
|
@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
### Fixed
|
||||
- Fix macro logic to support free variables on stubbed methods.
|
||||
|
||||
### Changed
|
||||
- Simplify string representation of mock-related types.
|
||||
- Remove unnecessary redefinitions of methods when adding stub functionality to a type.
|
||||
|
|
46
spec/issues/github_issue_48_spec.cr
Normal file
46
spec/issues/github_issue_48_spec.cr
Normal file
|
@ -0,0 +1,46 @@
|
|||
require "../spec_helper"
|
||||
|
||||
Spectator.describe "GitHub Issue #48" do
|
||||
class Test
|
||||
def return_this(thing : T) : T forall T
|
||||
thing
|
||||
end
|
||||
|
||||
def map(thing : T, & : T -> U) : U forall T, U
|
||||
yield thing
|
||||
end
|
||||
|
||||
def make_nilable(thing : T) : T? forall T
|
||||
thing.as(T?)
|
||||
end
|
||||
end
|
||||
|
||||
mock Test, make_nilable: nil
|
||||
|
||||
let(fake) { mock(Test) }
|
||||
|
||||
it "handles free variables" do
|
||||
allow(fake).to receive(:return_this).and_return("different")
|
||||
expect(fake.return_this("test")).to eq("different")
|
||||
end
|
||||
|
||||
it "raises on type cast error with free variables" do
|
||||
allow(fake).to receive(:return_this).and_return(42)
|
||||
expect { fake.return_this("test") }.to raise_error(TypeCastError, /String/)
|
||||
end
|
||||
|
||||
it "handles free variables with a block" do
|
||||
allow(fake).to receive(:map).and_return("stub")
|
||||
expect(fake.map(:mapped, &.to_s)).to eq("stub")
|
||||
end
|
||||
|
||||
it "raises on type cast error with a block and free variables" do
|
||||
allow(fake).to receive(:map).and_return(42)
|
||||
expect { fake.map(:mapped, &.to_s) }.to raise_error(TypeCastError, /String/)
|
||||
end
|
||||
|
||||
it "handles nilable free variables" do
|
||||
fake = mock(Test)
|
||||
expect(fake.make_nilable("foo")).to be_nil
|
||||
end
|
||||
end
|
|
@ -158,9 +158,11 @@ module Spectator
|
|||
# Cast the stub or return value to the expected type.
|
||||
# This is necessary to match the expected return type of the original method.
|
||||
_spectator_cast_stub_value(%stub, %call, typeof({{original}}),
|
||||
{{ if method.return_type && method.return_type.resolve == NoReturn
|
||||
{{ if method.return_type && method.return_type.resolve? == NoReturn
|
||||
:no_return
|
||||
elsif method.return_type && method.return_type.resolve <= Nil || method.return_type.is_a?(Union) && method.return_type.types.map(&.resolve).includes?(Nil)
|
||||
elsif method.return_type &&
|
||||
((resolved = method.return_type.resolve?).is_a?(TypeNode) && resolved <= Nil) ||
|
||||
(method.return_type.is_a?(Union) && method.return_type.types.map(&.resolve?).includes?(Nil))
|
||||
:nil
|
||||
else
|
||||
:raise
|
||||
|
@ -262,9 +264,10 @@ module Spectator
|
|||
{% if method.return_type %}
|
||||
# Return type restriction takes priority since it can be a superset of the original implementation.
|
||||
_spectator_cast_stub_value(%stub, %call, {{method.return_type}},
|
||||
{{ if method.return_type.resolve == NoReturn
|
||||
{{ if method.return_type.resolve? == NoReturn
|
||||
:no_return
|
||||
elsif method.return_type.resolve <= Nil || method.return_type.is_a?(Union) && method.return_type.types.map(&.resolve).includes?(Nil)
|
||||
elsif (method.return_type.resolve?.is_a?(TypeNode) && method.return_type.resolve <= Nil) ||
|
||||
(method.return_type.is_a?(Union) && method.return_type.types.map(&.resolve?).includes?(Nil))
|
||||
:nil
|
||||
else
|
||||
:raise
|
||||
|
|
Loading…
Reference in a new issue