Add initial support for exect-receive syntax

This commit is contained in:
Michael Miller 2022-07-12 19:11:44 -06:00
parent 3d7655a5d1
commit c91e288f61
No known key found for this signature in database
GPG key ID: 32B47AE8F388A1FF
2 changed files with 128 additions and 0 deletions

View file

@ -0,0 +1,80 @@
require "../../../spec_helper"
Spectator.describe "Deferred stub expectation DSL" do
context "with a double" do
double(:dbl) do
# Ensure the original is never called.
stub abstract def foo : Nil
stub abstract def foo(arg) : Nil
end
let(dbl) { double(:dbl) }
it "matches when a message is received" do
expect(dbl).to receive(:foo)
dbl.foo
end
it "matches when a message isn't received" do
expect(dbl).to_not receive(:foo)
end
it "matches when a message is received with matching arguments" do
expect(dbl).to receive(:foo).with(:bar)
dbl.foo(:bar)
end
it "matches when a message without arguments is received" do
expect(dbl).to_not receive(:foo).with(:bar)
dbl.foo
end
it "matches when a message without arguments isn't received" do
expect(dbl).to_not receive(:foo).with(:bar)
end
it "matches when a message with arguments isn't received" do
expect(dbl).to_not receive(:foo).with(:baz)
dbl.foo(:bar)
end
end
context "with a mock" do
abstract class MyClass
abstract def foo : Int32
abstract def foo(arg) : Int32
end
mock(MyClass)
let(fake) { mock(MyClass) }
it "matches when a message is received" do
expect(fake).to receive(:foo).and_return(42)
fake.foo(:bar)
end
it "matches when a message isn't received" do
expect(fake).to_not receive(:foo)
end
it "matches when a message is received with matching arguments" do
expect(fake).to receive(:foo).with(:bar).and_return(42)
fake.foo(:bar)
end
it "matches when a message without arguments is received" do
expect(fake).to_not receive(:foo).with(:bar)
fake.foo
end
it "matches when a message without arguments is received" do
expect(fake).to_not receive(:foo).with(:bar)
end
it "matches when a message with arguments isn't received" do
expect(fake).to_not receive(:foo).with(:baz).and_return(42)
fake.foo(:bar)
end
end
end

View file

@ -99,6 +99,14 @@ module Spectator
def initialize(@expression : Expression(T), @location : Location)
end
# Asserts that a method is called some point before the example completes.
@[AlwaysInline]
def to(stub : Stub, message = nil) : Nil
{% raise "The syntax `expect(...).to receive(...)` requires the expression passed to `expect` be stubbable (a mock or double)" unless T < ::Spectator::Stubbable || T < ::Spectator::StubbedType %}
to_eventually(stub, message)
end
# Asserts that some criteria defined by the matcher is satisfied.
# Allows a custom message to be used.
def to(matcher, message = nil) : Nil
@ -106,6 +114,20 @@ module Spectator
report(match_data, message)
end
# Asserts that a method is not called before the example completes.
@[AlwaysInline]
def to_not(stub : Stub, message = nil) : Nil
{% raise "The syntax `expect(...).to_not receive(...)` requires the expression passed to `expect` be stubbable (a mock or double)" unless T < ::Spectator::Stubbable || T < ::Spectator::StubbedType %}
to_never(stub, message)
end
# :ditto:
@[AlwaysInline]
def not_to(stub : Stub, message = nil) : Nil
to_not(stub, message)
end
# Asserts that some criteria defined by the matcher is not satisfied.
# This is effectively the opposite of `#to`.
# Allows a custom message to be used.
@ -120,6 +142,16 @@ module Spectator
to_not(matcher, message)
end
# Asserts that a method is called some point before the example completes.
def to_eventually(stub : Stub, message = nil) : Nil
{% raise "The syntax `expect(...).to_eventually receive(...)` requires the expression passed to `expect` be stubbable (a mock or double)" unless T < ::Spectator::Stubbable || T < ::Spectator::StubbedType %}
stubbable = @expression.value
stubbable._spectator_define_stub(stub)
matcher = Matchers::ReceiveMatcher.new(stub)
to_eventually(matcher, message)
end
# Asserts that some criteria defined by the matcher is eventually satisfied.
# The expectation is checked after the example finishes and all hooks have run.
# Allows a custom message to be used.
@ -127,6 +159,22 @@ module Spectator
Harness.current.defer { to(matcher, message) }
end
# Asserts that a method is not called before the example completes.
def to_never(stub : Stub, message = nil) : Nil
{% raise "The syntax `expect(...).to_never receive(...)` requires the expression passed to `expect` be stubbable (a mock or double)" unless T < ::Spectator::Stubbable || T < ::Spectator::StubbedType %}
stubbable = @expression.value
stubbable._spectator_define_stub(stub)
matcher = Matchers::ReceiveMatcher.new(stub)
to_never(matcher, message)
end
# :ditto:
@[AlwaysInline]
def never_to(stub : Stub, message = nil) : Nil
to_never(stub, message)
end
# Asserts that some criteria defined by the matcher is never satisfied.
# The expectation is checked after the example finishes and all hooks have run.
# Allows a custom message to be used.