Unit Testing in Phalcon 3 (upgrading from 2), DI can't find services

I'm having trouble migrating an old project from Phalcon 2 (2.0.9) to Phalcon 3 (3.1.2). The code itself seems to run ok (first look), but the unit-tests just won't work. I've been through the documentation (https://docs.phalconphp.com/en/3.0.1/reference/unit-testing.html) and even rebuild my TestHelper and UnitTestCase from scratch just to make sure that everything's in place, but especially the DI-container seems to work a lot differently in Phalcon 3 compared to Phalcon 2 in the tests.

For example:

  • "parent::setUp()" needs to be run at the beginnig of "setUp()" in UnitTestCase.
  • "parent::setUp()" at the end of UnitTestCase needs to be changed to "$this->setDi($di)"
  • The config is unknown in all tests unless you explicitely use "$this->setConfig($config)" in UnitTestCase (took me hours just to figure that out).
  • It seems I need to register "request" and "response" (as shared) in my DI to run any unit-test that needs the request- or response-object. This was not necessary before. Still the tests won't work, but at least the warning that the services "request/response" are unknown went away.
  • The "modelsManager" is now unknown to the DI, also I need to register "modelsMetadata" in the DI to get the unit-tests to work. This also was not necessary with Phalcon 2.

And it still won't work (although I fixed hundreds of warnings with the above fixes), right now I'm getting the message "Phalcon\Di\Exception: Service 'filter' wasn't found in the dependency injection container" when running a unit-test which tries to validate a form using "$form->isValid($post)" which was working fine this way with Phalcon 2.

I've been struggling with this for a couple of days now and starting to plan not to upgrade to Phalcon 3 at all but to keep an old server with Phalcon 2 running for legacy projects, even though this feels like failure ... is anyone experiencing the same problems and is this really the - hard to believe - way to go to upgrade to Phalcon 3?

Here's some of my code, TestHelper:

include __DIR__ . '/../../../vendor/autoload.php';
$loader = new \Phalcon\Loader();
$loader->registerDirs([ROOT_PATH]));
$loader->registerNamespaces( ... );
$loader->register();
$di = new FactoryDefault();
Di::reset();
Di::setDefault($di);

UnitTestCase (for each module):

abstract class UnitTestCase extends PhalconTestCase
{
    public function setUp()
    {
        parent::setUp();
        $di = Di::getDefault();
        (... setting my services as well as Request/Response here...)
       $this->setDi($di);
    }
}

Do you have tearDown? As i remember by defaul there is Di::reset()? Remove this line most likely.

edited Jun '17

Do you have tearDown? As i remember by defaul there is Di::reset()? Remove this line most likely.

I don't have tearDown() (and never had it in Phalcon 2) but added it right now: no change to the behaviour, even if I delete the line "parent::tearDown();" (where DI:reset() is called), so tearDown() won't do anything, but still the errors are the same.

edited Jun '17

https://github.com/phalcon/incubator/blob/master/Library/Phalcon/Test/UnitTestCase.php you use this class or not?

If yes then i had exactly same problem, i just needed to comment out Di::reset() and it works fine.

When lastly running tests for my project - i had everything fine with di.

If you can't figure it out then try to use xdebug to check what happens and where Di is reseted.

Commenting out Di::reset() didn't help, I got the same errors as before, when I don't register request/response/filter (and more) by myself. Phalcon 3.2.0 even made this worse (using 3.1.2 before), the line "use Phalcon\Config;" ist missing in the UnitTestCase.php in the incubator, so the Test will try to find "Phalcon\Test\Config" which doesn't exist ...

edited Jun '17

Oh, you are right. Good to know this.

Then use xdebug to figure out why your services are removed or why you have diffrent DI instance.

I use Phalcon 3 and when was running last time tests for my project everything was fine, but it was loooong time ago.