开发者

PHPUnit - test autoloader class

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.


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.


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


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).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜