PHPUnit - 测试自动加载器类

发布于 2024-12-05 08:01:34 字数 68 浏览 0 评论 0原文

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

I need to create an autoloader to my application. I don't want to depend on a file in the filesystem, so how do I mock a new call? Or how do you test an autoloader class?
Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

秋心╮凉 2024-12-12 08:01:34

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

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

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

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

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

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

Or how do you test an autoloader class

Imho you don't need to unit test your autoloader at all.

If you bootstrap your application it will ether crash really hard because it can find all the needed classes or your autoloader works fine.

Every single test in your test suite will test that the autoloader is able to load the "class under test" so i wouldn't worry to much about unit testing it.

Maybe call it "integration testing as a side effect" if you want but I'd say thats good enough.

If you don't think thats good enough I'd put the require/include statement in a protected function and override that function in a test autoloader and check if it receives the right values.

不乱于心 2024-12-12 08:01:34

创建一些专门用于测试自动加载器的类文件,并将它们放在可以向自动加载器注册的单独目录(与测试同级)中。使用 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');
    }
}

更新: 哇,我不知道我是如何错过“我不想要依赖于文件系统中的文件”在你的问题中,但这非常关键。您需要将对 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'));
}

Create some class files specifically for testing your autoloader, and place them in a separate directory (sibling to the test) that you can register with the autoloader. Use class_exists($class, false) to test if a class is loaded without invoking the autoloader.

Note: It helps if you design your autoloader to be non-static so that you can instantiate a separate instance for the test instead of testing the active one.

Here are the tests for the autoload() method of my custom autoloader as an example:

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');
    }
}

Update: Wow, I don't know how I missed "I don't want to depend on a file in the filesystem" in your question, but that's pretty key. You'll need to place the call to include in its own method of your autoloader (e.g. includeFile($path)). This will allow you to mock the method during the test so you don't involve files on disk. Beyond that you test the class as you normally would: feed it inputs (as above) of classes to be autoloaded and validate that your class calls includeFile() with the correct paths when it should.

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'));
}
水中月 2024-12-12 08:01:34

如何测试自动加载器类?

取决于自动加载器类的作用。例如,您可以测试注册自动加载回调是否适用于 spl_autoload_register

或者,如果您的自动加载器提供了一个 LoadLibrary 函数来加载库的所有类和接口,以检查是否所有类都已加载。但这通常取决于文件系统(我认为这是可以的)。

how do you test an autoloader class?

Depends on what the autoloader class does. For example you can test if registering the autoload callback did work with spl_autoload_register.

Or if your autoloader provides a LoadLibrary function that loads all classes and interfaces of your library, to check if all classes have been loaded. But this normally depended to the file system (which I think is okay).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文