在我的 Drupal 10.x 项目中,我有一个测试试图模拟我创建的供多个测试使用的类(称之为
Drupal\Tests\my_module\MyTestObject
)。代码看起来像这样:
protected function setUpMocks(): void {
$myMockObject = $this->createMock(MyTestObject::class);
}
我已经检查了类的名称、定义它的文件的名称以及文件的整个目录路径,但无论如何,我收到以下错误:
PHPUnit\Framework\MockObject\UnknownTypeException: Class or interface "Drupal\Tests\my_module\Utilities\MyTestObject" does not exist
此外,如果我在扩展该类的测试类之上定义一个抽象类(见下文),那么 PHP 会指示找不到基类:
namespace Drupal\Tests\my_module\Functional;
use Drupal\Tests\my_module\Utilities\MyTestObject;
// PHP fails to locate the MyTestObject base class.
abstract class SomeClass extends MyTestObject {
}
/**
* My functional tests.
*/
class SomeTest extends BrowserTestBase {
// ...
}
为什么这个类不自动加载?看起来 PHP 可以毫无问题地找到几乎在同一个包中的其他测试类。
我大约 95% 确信答案就在
\Drupal\Core\Test\TestDiscovery::registerTestNamespaces()
。此方法在运行时向类加载器动态注册每个扩展(模块、主题、配置文件等)的名称空间。根据以下代码片段,该方法仅期望在特定于每种测试类型的顶级文件夹下找到与测试相关的代码,因此代码必须存在于这些路径之一中才能正确自动加载:
$this->testNamespaces["Drupal\\Tests\\$name\\Unit\\"][] = "$base_path/tests/src/Unit";
$this->testNamespaces["Drupal\\Tests\\$name\\Kernel\\"][] = "$base_path/tests/src/Kernel";
$this->testNamespaces["Drupal\\Tests\\$name\\Functional\\"][] = "$base_path/tests/src/Functional";
$this->testNamespaces["Drupal\\Tests\\$name\\Build\\"][] = "$base_path/tests/src/Build";
$this->testNamespaces["Drupal\\Tests\\$name\\FunctionalJavascript\\"][] = "$base_path/tests/src/FunctionalJavascript";
// Add discovery for traits which are shared between different test
// suites.
$this->testNamespaces["Drupal\\Tests\\$name\\Traits\\"][] = "$base_path/tests/src/Traits";
由于我的类位于命名空间
Drupal\Tests\my_module\Utilities
中(在磁盘上保存为 web/modules/custom/my_module/tests/src/Utilities/MyTestObject.php
),因此它不在测试命名空间之一下,因此该文件不符合自动加载的条件。将类移动到 Drupal\Tests\my_module\Functional\Utilities
是有效的,就像将类放入测试安装的模块的 src/
中一样。因此,如果您想在单元测试和功能测试之间共享测试装置,则需要注意这一点。