PHPUnit - 测试自动加载器类

tho*_*hom 5 php phpunit mocking autoload spl-autoload-register

我需要为我的应用程序创建一个自动加载器.我不想依赖文件系统中的文件,那么如何模拟新的调用呢?或者你如何测试自动加载器类?谢谢.

edo*_*ian 5

或者如何测试自动加载器类

恕我直言,您根本不需要对自动加载器进行单元测试。

如果你引导你的应用程序,它会严重崩溃,因为它可以找到所有需要的类,或者你的自动加载器工作正常。

测试套件中的每个测试都会测试自动加载器是否能够加载“被测类”,因此我不会太担心对其进行单元测试。

如果您愿意,可以将其称为“作为副作用的集成测试”,但我想说这已经足够好了。

如果您认为这还不够好,我会将 require/include 语句放入受保护的函数中,并在测试自动加载器中覆盖该函数,并检查它是否收到正确的值。


Dav*_*ess 1

创建一些专门用于测试自动加载器的类文件,并将它们放在可以向自动加载器注册的单独目录(与测试同级)中。用于class_exists($class, false)测试类是否在不调用自动加载器的情况下加载。

注意:如果您将自动加载器设计为非静态的,这样您就可以为测试实例化一个单独的实例,而不是测试活动的实例,这会有所帮助。

以下是我的自定义自动加载器方法的测试autoload()作为示例:

function test_autoload_loadsExistingClass() {
    $this->fixture->registerPrefix('TestClasses', self::$root . 'models');
    if (class_exists('TestClasses_Autoloader_Foo', false)) {
        self::error('Class TestClasses_Autoloader_Foo is already loaded');
    }
    $this->fixture->autoload('TestClasses_Autoloader_Foo');
    if (!class_exists('TestClasses_Autoloader_Foo', false)) {
        self::fail('Class TestClasses_Autoloader_Foo failed to load');
    }
}

function test_autoload_silentlyIgnoresMissingClasses() {
    $this->fixture->registerPrefix('Foo', self::$root . 'models');
    $this->fixture->autoload('Foo_Bar');
}

function test_autoload_searchesIncludePathForUnknownPrefix() {
    if (class_exists('TestClasses_Autoloader_Foo', false)) {
        self::error('Class TestClasses_Autoloader_Foo is already loaded');
    }
    set_include_path(self::$root . 'include' . PATH_SEPARATOR . self::$savedIncludePath);
    $this->fixture->autoload('TestClasses_Autoloader_Foo');
    if (!class_exists('TestClasses_Autoloader_Foo', false)) {
        self::fail('Class TestClasses_Autoloader_Foo failed to load');
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:哇,我不知道我是如何错过你的问题中的“我不想依赖文件系统中的文件”的,但这非常关键。您需要将调用放在include自动加载器自己的方法中(例如includeFile($path))。这将允许您在测试期间模拟该方法,这样就不会涉及磁盘上的文件。除此之外,您可以像平常一样测试该类:向其提供要自动加载的类的输入(如上所述),并验证您的类是否includeFile()在应该时使用正确的路径进行调用。

function testAutoloadLoadsExistingClass() {
    $fixture = $this->getMock('MyAutoloader', 
            array('includeFile'),  // mock the call to `include`
            array(...));           // constructor args
    $fixture->expects($this->once())
            ->method('includeFile')
            ->with('My/Package/Class')
            ->will($this->returnValue(true));
    self::assertTrue($fixture->autoload('My_Package_Class'));
}
Run Code Online (Sandbox Code Playgroud)