From 754bfd693922a2e9b5c095ed0ec710c3f0d60865 Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Tue, 12 Jul 2022 23:02:20 -0600 Subject: [PATCH] Intercept most exit calls and raise instead --- spec/issues/github_issue_29_spec.cr | 19 ++++--------------- spec/spectator/system_exit_spec.cr | 13 +++++++++++++ src/spectator/includes.cr | 1 + src/spectator/system_exit.cr | 25 +++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 15 deletions(-) create mode 100644 spec/spectator/system_exit_spec.cr create mode 100644 src/spectator/system_exit.cr diff --git a/spec/issues/github_issue_29_spec.cr b/spec/issues/github_issue_29_spec.cr index 27a8e6d..8458783 100644 --- a/spec/issues/github_issue_29_spec.cr +++ b/spec/issues/github_issue_29_spec.cr @@ -7,14 +7,9 @@ Spectator.describe "GitHub Issue #29" do end end - # mock SomeClass do - # inject_stub abstract def exit(code) - # end - describe SomeClass do - xit "captures exit", pending: "Mock redesign" do - expect(subject).to receive(:exit).with(0) - subject.goodbye + it "captures exit" do + expect { subject.goodbye }.to raise_error(Spectator::SystemExit) end end @@ -25,16 +20,10 @@ Spectator.describe "GitHub Issue #29" do end end - # mock Foo do - # inject_stub abstract def self.exit(code) - # end - subject { Foo } - xit "must capture exit", pending: "Mock redesign" do - expect(subject).to receive(:exit).with(0) - - subject.test + it "must capture exit" do + expect { subject.test }.to raise_error(Spectator::SystemExit) end end end diff --git a/spec/spectator/system_exit_spec.cr b/spec/spectator/system_exit_spec.cr new file mode 100644 index 0000000..49cc4f6 --- /dev/null +++ b/spec/spectator/system_exit_spec.cr @@ -0,0 +1,13 @@ +require "../spec_helper" + +Spectator.describe Spectator::SystemExit do + it "is raised when an attempt is made to exit the application" do + expect { exit }.to raise_error(described_class) + end + + it "has the status code passed to an exit call" do + exit 5 + rescue error : Spectator::SystemExit + expect(error.status).to eq(5) + end +end diff --git a/src/spectator/includes.cr b/src/spectator/includes.cr index d649827..10c1698 100644 --- a/src/spectator/includes.cr +++ b/src/spectator/includes.cr @@ -51,6 +51,7 @@ require "./runner_events" require "./runner" require "./spec_builder" require "./spec" +require "./system_exit" require "./tag_node_filter" require "./test_context" require "./value" diff --git a/src/spectator/system_exit.cr b/src/spectator/system_exit.cr new file mode 100644 index 0000000..95a2b22 --- /dev/null +++ b/src/spectator/system_exit.cr @@ -0,0 +1,25 @@ +module Spectator + # Indicates a call to exit the application was performed. + class SystemExit < Exception + # Status code passed to the exit call. + getter status : Int32 + + # Creates the exception. + def initialize(message : String? = nil, cause : Exception? = nil, @status : Int32 = 0) + super(message, cause) + end + end + + # Allow Spectator to exit normally when needed. + private def self.exit(status = 0) : NoReturn + ::Crystal::System::Process.exit(status) + end +end + +class Process + # Replace the typically used exit method with a method that raises. + # This allows tests to catch attempts to exit the application. + def self.exit(status = 0) : NoReturn + raise ::Spectator::SystemExit.new(status: status) + end +end