3

I'm writing some unit tests for a class loader, and the first test is there to assert that trying to reference a class without loading it first will indeed fail.

The test looks like this:

/**
 * @expectedException PHPUnit_Framework_Error
 */
public function testInstantiateUnloadedClass() {
    $foo = new Foo();
}

Sadly, running the test yields this message:

PHP Fatal error: Class 'Foo' not found in /Users/jfvaren/workspace/classloader/ClassLoaderTest.php on line 7

Must I simply accept that this is not doable?

1
  • There might be a workaround for this (reinvoke via external interpreter). But that's not really what unittests shall accomplish. (For simplicity combine with PHPT.)
    – mario
    Commented Sep 2, 2011 at 20:59

3 Answers 3

4

Call class_exists(), this tries to autoload the class and returns boolean false if it isn't able to.

http://php.net/manual/en/function.class-exists.php

1
  • That seems to be the cleanest option, Robert. I'll just use assertFalse(class_exists('Foo')) to achieve the same thing. Thanks! Commented Sep 2, 2011 at 21:28
2

To test if the class is intantiated or not you can simply do something along the lines of:

try {
     if( !class_exists( "Foo" ) )
          throw new Exception( "Foo does not exist." );
}catch( Exception $e ){
     $e->showMessage();
}

Moreover, if you want to test if it exists when it is actually referenced (and you don't want to do class_exists first) you can do so in an AutoLoader. I've included more on this below, along with an example die statement.

Notes on an AutoLoader

Now, possibly off-topic, if you want to be able to include a class dynamically without explicitly having referenced it, you can by instantiating an AutoLoader. AutoLoaders look for a class file when a class is referenced, and then includes it before trying to use it.

So, for example, you would need to include AutoLoader.php in your Test.php file, as well as every other file using the class. This file would then include other files as needed.

To do this, you need to set up your AutoLoader.php file. It will need to look something like this:

// This tells PHP what to use to load the functions
ini_set( 'unserialize_callback_func', '__autoload' );

// Create an array pairing class names to their file include path
$myClasses = array( "Foo" => "Foo.php", "Bar" => "Bar.php" );

class AutoLoader {

    static function autoload( $class ){
        if( !in_array( $class, $myClasses ) )
            die( "The class {$class} doesn't exist!" );
        require( $myClasses[$class] );
    }

}

if( function_exists( 'spl_autoload_register' ) ) {
    spl_autoload_register( array( 'AutoLoader', 'autoload' ) );
} else {
    function __autoload( $className ){
        # When called, load a previously unloaded class
        AutoLoader::autoload( $className );
    }
}
1

It seems that it's impossible to catch FATAL ERROR. So instead of using in __autoload require you can use include with if statement and generate a specific exception.

Not the answer you're looking for? Browse other questions tagged or ask your own question.