1
votes

This is a question on proper coding of PHPUnit Tests in Zend Framework 2, using Object Oriented code principles.

I have the following PHPUnit Test Case:

namespace FedcoUserTest;
use FedcoUser\Controller\MachinistController;

class MachinistControllerTest extends Framework\TestCase
{...}

My MachinistController class is as such:

namespace FedcoUser\Controller;

class MachinistController extends \ZfcUser\Controller\UserController
{...}

When trying to run the test case, I would get this error:

Debug Error: MachinistController.php - Class 'ZfcUser\Controller\UserController' not found

That was weird, because my MachinistController class was running just fine and was finding ZfcUser's controller when ran as a web application, and not through the PHPUnit Test.

Somehow I've decided to put a

require_once 'vendor/zf-commons/zfc-user/src/ZfcUser/Controller/UserController.php';

line into my MachinistControllerTest class, and now my PHPUnit test runs without errors.

I found that to be weird.

Why: so far in my experience with ZF2, I have not had the need for use of require functions. ZF2 is fully OO, so why now? It may be correct, but is there a better way, and if so, what is it?

More specific Questions:

  • (correctness) Am I right to use this require_once line in my code to make the test case pass?
  • (ZF2 best practices) Why would I use a require_once() statement in my otherwisely totally OO ZF2 code (Use of require seems to me like a procedural code smell)?
  • (OO best practices) Why was ZfcUser's controller not being found, when my MachinistController was perfectly extending it?
3

3 Answers

1
votes

I ended up loading additional namespaces into my config inside my TestConfiguration.php file:

$additionalNamespaces = array(
    'ZfcUser\Controller' => __DIR__ . '/../../../vendor/zf-commons/zfc-user/src/ZfcUser/Controller/'
);

that fit in nicely into my bootstrap.php, which had the following code:

// setup autoloader
AutoloaderFactory::factory(
    array(
        'Zend\Loader\StandardAutoloader' => array(
            StandardAutoloader::AUTOREGISTER_ZF => true,
            StandardAutoloader::ACT_AS_FALLBACK => false,
            StandardAutoloader::LOAD_NS => $additionalNamespaces,
        )
    )
);
0
votes

please don't forget that PHPUnit Tests are not Part of ZF2 Framework. ZF2 is not responsible for autoloading classes in Unit Test files.

You need to Mock Classes http://phpunit.de/manual/3.6/en/test-doubles.html#test-doubles.mock-objects by your own and are responsible to require all classes by your own.

0
votes

Typically you would use PHPUnit's bootstrap functionality to bootstrap some elements of your app (including the autoloader) before running the tests. There's an example bootstrap in the manual: http://framework.zend.com/manual/2.0/en/user-guide/unit-testing.html. Personally I use a slightly modified version of this that also pulls in the Composer autoloader. Then you don't need to require any classes in your tests.