【问题标题】:'Class not found' when using namespaces in PHPUnit在 PHPUnit 中使用命名空间时出现“找不到类”
【发布时间】:2013-03-21 02:26:42
【问题描述】:

我是 PHPUnit 的新手,在设置它以访问我的 PHP 文件时遇到了一些麻烦。我用于我的应用程序的目录结构是这样的:

./phpunit.xml

./lib/Application/
  -> Dir1/File1.php (namespace = Application\Dir1)
  -> Dir1/File2.php
  -> Dir2/File1.php (namespace = Application\Dir2)

./tests/Application/Tests
  -> Test1.php (namespace = Application\Tests)
  -> Test2.php 

在我的 PhpUnit.xml 中,我有:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit verbose="false">
  <testsuites>
      <testsuite name="Application">
          <directory>./tests/Application/Tests</directory>
      </testsuite>
  </testsuites>
  <logging>
       <log type="coverage-text" target="php://stdout" showUncoveredFiles="false"/>
       <log type="json" target="/tmp/phpunit-logfile.json"/>
  </logging>
  <filter>
        <whitelist>
            <directory suffix=".php">./lib</directory>
        </whitelist>
  </filter>
</phpunit>

在我的一个测试文件中,我打开:

namespace Application\Tests;

use Application\Dir1\File1;

class MyTest extends File1 {}

但它一直在说:

找不到类“Application\Dir1\File1”

我哪里错了?

【问题讨论】:

  • 如何从测试文件中加载 Dir1/File1.php? use 声明并不意味着您不需要必要的文件。
  • 我尝试使用引用 Autoload.php 的引导文件 - 但我不确定使用什么功能来包含所有必要的文件。我还认为 PHPUnit.xml 会自动在 &lt;filter&gt; 节点中包含所需的文件。不是这样吗?
  • 尝试将require_once 声明放在开头,它应该可以工作。
  • 所以对于我写的每个测试,我必须require_once每个文件?这不会破坏使用命名空间自动加载文件的全部目的吗?似乎有点 hacky...
  • 您可以使用这种方法:php.net/manual/en/language.oop5.autoload.php

标签: php namespaces phpunit


【解决方案1】:

即使您使用use,您仍然必须包含该文件,方法是使用includerequireinclude_oncerequire_once,或者使用spl_autoload_register 包含该文件,像这样:

spl_autoload_register(function ($class)
{
    include '\lib\\' . $class . 'php';
});

当您尝试使用Application\Dir1\File1 时,脚本将自动运行include '\lib\Application\Dir1\File1.php'

【讨论】:

  • 你是对的。但我想摆脱手动指定依赖项并转向更自动化的解决方案。我的解决方案使用了一种方法 - 但无论如何谢谢:)
  • 您的方式如何更加自动化?它看起来几乎一样,只是开销更大。
  • 好吧,一方面,这不是处理目录分隔符(针对不同的操作系统),而更全面的类可以处理。但是您确实为我指明了正确的方向 - 所以我将其标记为已接受的解决方案是公平的。
  • DS 上的要点。虽然你可以简单地使用str_replace('\\', DIRECTORY_SEPARATOR, $class);
【解决方案2】:

我发现 Jonathan Wage 的 class autoloader 非常有用,它允许 PHPUnit 测试从不同目录访问命名空间。在我的 bootstrap.php 中,我只是指定了位置和关联的模块命名空间:

require_once 'SplClassLoader.php';

$classLoader = new SplClassLoader('Application', dirname(__FILE__) . '/../lib');
$classLoader->register();

【讨论】:

  • +1 用于提及 bootstrap.php。这就是我的设置加载自定义 autoader 的地方。
  • 我正是这样做的,但它找不到类。它似乎也不会递归地进入所有目录。
【解决方案3】:

如果您使用 Composer 安装 PHPUnit,那么您可以使用 Composers 自动加载器。最简单的方法是添加:

"autoload":{
    "psr-0":{
        "your-app-directory":""
    }
}

到 composer.json

【讨论】:

  • 我用composer安装了phpunit,但这并没有解决问题。甚至使用 psr-4 甚至交换“your-app-directory”和“”
  • @Leggy7 你能把你想用的东西发给我吗
  • 请提及使用'composer dump-autoload'
【解决方案4】:

我有同样的问题。 我也在使用作曲家,唯一为我解决的问题是:

  1. 在 autoload 部分的 composer.json 文件中添加一个带有根命名空间的类映射部分

    "autoload":  {
            "classmap": ["namespaceRoot/"]
    }
    
  2. 执行composer dump-autoload 命令以重新创建您的自动加载文件(包含所有类映射!)

【讨论】:

  • 作曲家 dump-autoload 解决了我 1 小时的头痛问题:D,谢谢队友
猜你喜欢
  • 2015-12-12
  • 2020-02-10
  • 2016-08-15
  • 2012-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-10
相关资源
最近更新 更多