首先,标题表明这是 this 或 this 的重复,但由于几个原因,这些答案对我不起作用,即使我最初的问题是相同的。我会解释为什么。
我的问题是这样的:我的代码中有几次我想发送标头和正文,然后终止处理。与其他问题不同,我不能使用
return
或抛出异常(这些显然是为不同目的而设计的不同函数,而不是退出,这不是错误;这只是在某些特定情况下提前运行时终止)。
不过,我想编写运行这些方法的单元测试,确保设置了适当的标头(在here找到解决方案),输出正文正确(使用测试用例中的
$this->expectOutputString()
方法解决)并且然后继续测试。在这之间,将会发生exit
。
我已经在 PHPUnit 中尝试了
@runInSeparateProcess
注释,我还检查了 test_helpers 扩展,它可以工作,但我不想添加另一个扩展(请注意,测试也将在生产中运行)一行本地 PHP 代码就破坏了一切。必须有一种更简单的方法而不牺牲最佳实践。
有没有人有好的办法解决这个问题?
我在引导程序中添加了一个变量,在我需要不退出的极少数情况下,我可以在代码中使用 IF 引用该变量。
define ('PHPUNIT_RUNNING', 1);
正常程序:
if(! @PHPUNIT_RUNNING === 1 )
{
exit;
}
PHPUnit 没有被定义为规则,所以在 PHP 执行时会产生一个警告(我们用 @ 隐藏它。代码会在不处于测试模式时执行我们想要的操作。这是在编写主代码后添加的因为我们将 PHPUnit 测试添加到现有项目中,而不是进行 TDD。
请注意:
我们尽可能少地这样做以解决遗留问题,否则我们会按照其他人的建议进行操作并抛出异常或将数据返回到父函数。
我刚刚测试了以下想法:
退出异常.php:
<?php
class DieException extends Exception {} // for those people who like die as well as exit
class ExitException extends Exception {}
入口点.php:
<?php
require_once 'ExitException.php';
try {
require 'main_code.php';
run_main_code();
}
catch (DieException $e) {
return $e->getMessage();
}
catch (ExitException $e) {
return $e->getMessage();
}
几个
include
之后:
深度代码.php
<?php
throw new ExitException('Exiting normally');
这模拟了在最顶层捕获的
exit
或 die
。您的程序将像以前一样退出,现在可以在不终止整个测试套件的情况下进行测试。唯一的问题是,如果您还在现有代码中捕获其他普通 Exception
,在这种情况下,您将必须修改代码以重新抛出 DieException
/ExitException
直到它们到达顶层。
另一种选择是干净地返回,这可能需要重写大量代码。也就是说,如果您当时没有退出,为什么您的程序会生成进一步的输出?它应该尽早检查是否需要“提前退出”,然后调用该代码并继续执行程序的自然结束。
如果您必须处理第三方库或其他您不应该或不能更改的代码,那么这个问题就会变得更加困难,但除非它们带有自己的单元测试,否则为它们编写测试没有任何价值,因为理想情况下,您不应更改第三方代码以避免将来出现兼容性问题。一个编写良好的第三方库永远不应该
die
。它应该始终将控制权返回给调用程序,或者抛出一个可以捕获的 Exception
。
exit;
是确保线程在那里停止的简单方法,但它不会让您处于进行单元测试的良好位置。
将
exit;
包装在类中的函数中,您可以在单元测试中模拟该函数。
从被测试的代码中调用该函数,而不是 exit;
那么问题是你需要添加一个 return;
到