PHPUnit:您能否排除第 3 方库将其通知转换为异常?带有 convertNoticesToExceptions 的 EG

标签 php unit-testing composer-php phpunit

作为最佳实践,我一直在运行 PHPUnit 并启用 convertNoticesToExceptions。 https://phpunit.readthedocs.io/en/9.5/configuration.html#the-convertnoticestoexceptions-attribute

当然,这只适用于我自己的代码:我更愿意为(例如)vendor/ 设置不同的设置。这并不是说我要修复第三方代码抛出的所有通知。

文档没有建议不同目录的设置可以不同。 (我依稀记得读过有关忽略图书馆通知的方法,但可能是错误的。)

我知道如何使用 @,但这解决了另一个问题。

这不是一个选择吗?

最佳答案

为了简洁起见,假设您的项目中有两个类:

namespace MyNamespace;

class Foo
{
    public function myFunc(): bool
    {
        $i = [];
        $i["1"];

        return true;
    }
}
namespace MyNamespace;

class Bar
{
    public function myFunc(): bool
    {
        $i = [];
        $i["1"];

        return true;
    }
}

这两个函数 myFunc 都会触发 w 警告(不知道什么会在 PHP 8.1 中触发通知),但我们不想为类 Foo 报告它.

您的测试将如下所示:

namespace MyNamespace\Tests;

use PHPUnit\Framework\TestCase;
use MyNamespace\Foo;
use MyNamespace\Bar;

class MyTest extends TestCase
{
    protected function setUp(): void
    {
        set_error_handler(static function (int $errorNr, string $errorStr, string $errorFile, int $errorLine, array $errorContext = []): bool {
            if (str_contains('/home/awons/Projects/test/src/Foo.php', $errorFile) && $errorNr === E_WARNING) {
                return true;
            }
            
            $phpUnitHandler = new \PHPUnit\Util\ErrorHandler(true, true, true, true);
            return $phpUnitHandler->__invoke($errorNr, $errorStr, $errorFile, $errorLine, $errorContext);
            
        });
    }

    protected function tearDown(): void
    {
        restore_error_handler();
    }

    public function testFoo(): void
    {
        $foo = new Foo();
        self::assertTrue($foo->myFunc());
    }

    public function testBar(): void
    {
        $bar = new Bar();
        self::assertTrue($bar->myFunc());
    }

    public function testFooAgain(): void
    {
        $foo = new Foo();
        self::assertTrue($foo->myFunc());
    }
}

这并不是最高效的解决方案,我认为它是一种 hack,但如果您需要的话,它应该可以解决问题。

您所要做的就是决定何时触发 PhpUnit 的错误处理程序以及何时忽略通知。您可以将 /home/awons/Projects/test/src/Foo.php 替换为 /vendor/ (或任何更具体的内容以 100% 确定您获得了正确的路径).

此外,我不确定如何获取错误处理程序的当前设置。您可能需要为此解析配置文件,或者只是将所有内容移动到基类并在那里硬编码值(只是让它们与实际设置同步)。

::编辑:: 甚至还有一种方法可以不实例化 PhpUnit 的处理程序,而只是从当前上下文中获取它。我们所要做的就是注册一个空的错误处理程序并立即恢复它。注册一个新的错误处理程序会返回前一个错误处理程序。 假设基类在 ./tests 中,您可以构建以下抽象测试用例:

use PHPUnit\Framework\TestCase;

abstract class BaseTestCase extends TestCase
{
    protected function setUp(): void
    {
        $phpUnitErrorHandler = set_error_handler(function () {
        });
        restore_error_handler();
        set_error_handler(
            static function (
                int $errorNr,
                string $errorStr,
                string $errorFile,
                int $errorLine,
                array $errorContext = []
            ) use ($phpUnitErrorHandler): bool {
                $vendorDir = realpath(__DIR__ . "/../vendor/");
                if (str_contains($vendorDir, $errorFile) && $errorNr === E_NOTICE) {
                    return true;
                }
                return call_user_func_array(
                    $phpUnitErrorHandler,
                    [$errorNr, $errorStr, $errorFile, $errorLine, $errorContext]
                );
            }
        );
    }

    protected function tearDown(): void
    {
        restore_error_handler();
    }
}

关于PHPUnit:您能否排除第 3 方库将其通知转换为异常?带有 convertNoticesToExceptions 的 EG,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73152935/

相关文章:

php - 您的要求无法解析为一组可安装的软件包

composer-php - Composer --> 未安装列出的更新包,忽略

composer-php - Composer why-not没有帮助 - 为什么我不能安装这个包

php - bindParam()、bindValue()和execute(array())有什么区别和优势

c# - 如何测试返回 Ok(object) 的 ASP.NET Core 2.2 Web API GET IActionResult?

php - Laravel Mail ShouldQueue 与 Job ShouldQueue

unit-testing - 如何在Spock单元测试中测试Groovy构造函数并覆盖100%的代码

xml - 如何在 hudson 中集成 erlang 单元测试?

php - 如何通过直接SQL查询在magento中设置产品的special_price?

PHP mail() 函数不发送电子邮件