Reputation: 9008
For a library I am writing I would like to be able to mock the exit
PHP function.
I tried to use php-mock to provide a namespaced version of exit
, something like
namespace MyNamespace;
function exit()
{
// my mocked version of the function
}
But this creates problems to the parser, which throws the following ParseError
: syntax error, unexpected 'exit' (T_EXIT), expecting '('
.
Is there any other way to mock a built in function without incurring in parsing problems? Should I try to modify the AST with something like BetterReflection?
Upvotes: 4
Views: 1070
Reputation: 11
Since PHP 8.1, Fibers have been introduced, and I was drafting an idea to use them to interrupt execution and handle it after the interruption without terminating the PHP process.
What I have in mind is to wrap the logic inside a Fiber like this:
<?php
function run(callable $operation): mixed
{
$fiber = new \Fiber($operation);
$suspended = $fiber->start();
if ($suspended instanceof ExitException) {
return $suspended;
}
return $fiber->getReturn();
}
function mockedExit(): void {
\Fiber::suspend(new ExitException('exit'));
}
$response = run(static function () {
// Some Logic
if (true) {
mockedExit();
}
// Continue Logic
return 'SUCCESS';
});
if ($response === 'SUCCESS') {
echo 200;
} else {
echo 500;
}
class ExitException extends \Exception {}
What I'm proposing here is to suspend the execution using Fibers since they support full-stack functions. I can foresee some trade-offs, such as managing the complexity of nested Fibers, but I don't see any immediate concerns.
Upvotes: 0
Reputation: 9008
As per comments, I guess that mocking language constructs is not feasible.
To test exit()
I ended up spawning other processes with exec
and asserting on their output and exist status
Upvotes: 1