Phalcon Models with PHPUnit and DI container

With the 2.0 version, when I tried to use static methods of my Models from my PhpUnits tests, I'd the following error : "Phalcon\Di\Exception: Service 'modelsManager' wasn't found in the dependency injection container"

Since the 2.1 RC version, there is the same problem, with instanciation of my models too...

Anybody can explain me how to use the models within my tests ? or How to contourn this problem ?

Thanks for advance

Adding "DI::setDefault($this->getDI());" at the top of the Test Methods concerned allow me to contourn the problem (but not to solve it)...

I don't understand why I need that... my test class is a child of the unitTestCase, and the DI is defined in unitTestCase setUp()...

If anybody has a response, Thanks for advance...

But now, I've another problem...

You need to configure defaut DI in your UnitTestCase, which will contain all necessary services for your model like db, modelsManages, modelsMetadata, etc.

or

If you want pure unit tests, you can use http://codeception.com/ where you can mock static methods

Thanks for your answer !

In my UnitTestCase are these lines :

    $di = new FactoryDefault();

(...)

    $di->set(
        'modelsManager',
        function()
        {
            return new \Phalcon\Mvc\Model\Manager();
        }
    );

(...)

    DI::setDefault($di);
    parent::setUp($di);
    parent::setDi($di);

That's why I don't understand my problem... An idea ?

edited Apr '16

Please post whole your UnitTestCase and setUp method in your particular test which is not working.

edited Jun '16

if any one can to help me with identical error, please do it)

TestHelper.php

define('ROOTPATH', DIR); define('PATHLIBRARY', DIR . '/../app/library/'); define('PATHSERVICES', DIR . '/../app/services/'); define('PATHRESOURCES', DIR . '/../app/resources/');

define('APPPATH', realpath(DIR . '/..') . '/'); define('LIBPATH', APPPATH . 'common/lib/'); define('MODELSPATH', APPPATH . 'common/models/'); define('COLLECTIONSPATH', APPPATH . 'common/collections/'); define('CONFIGPATH', APPPATH . 'common/config/'); define('TEMPPATH', APP_PATH . 'temp/');

setincludepath( ROOTPATH . PATHSEPARATOR . getincludepath() );

// required for phalcon/incubator include DIR . "/../vendor/autoload.php";

requireonce(CONFIGPATH . 'config.php');

// use the application autoloader to autoload the classes // autoload the dependencies found in composer $loader = new \Phalcon\Loader();

$loader->registerDirs(array( ROOT_PATH ));

Register common namespaces

$loader->registerNamespaces(array( 'App\Models' => MODELSPATH, 'App\Collections' => COLLECTIONSPATH, 'App\Lib' => LIB_PATH, ));

$loader->register();

$di = new FactoryDefault(); DI::reset();

Register config

requireonce(CONFIGPATH . 'services.php'); // add any needed services to the DI here

DI::setDefault($di);


service.php

<?php

Register DB

$di->setShared('mongo', function () use($config) { $mongo = new MongoClient('mongodb://mongo:27017'); return $mongo->selectDB($config->mongo->name); });

$di->setShared('collectionManager', function(){ return new Phalcon\Mvc\Collection\Manager(); });

Mailer (requires composer component)

$di->setShared('mailer', function () use($config) { $mailer = new \App\Lib\Mailer([ 'templates' => APP_PATH . 'common/emails/', 'host' => $config->smtp->host, 'port' => $config->smtp->port, 'username' => $config->smtp->username, 'password' => $config->smtp->password, 'security' => $config->smtp->security ]);

if (!empty($config->project->admin_email) && !empty($config->project->admin_name)) {
    $mailer->setFrom($config->project->admin_email, $config->project->admin_name);
}

return $mailer;

});

Logger

$di->setShared('logger', function() use($config, $di) { $logger = new \Phalcon\Logger\Multiple;

$logger->push(new \Phalcon\Logger\Adapter\File($config->project->log_path));
$logger->push(new \Phalcon\Logger\Adapter\Stream('php://stdout'));

return $logger;

});

$di->setShared('crypt', function() use($config) { $crypt = new \Phalcon\Crypt(); $crypt->setMode(MCRYPTMODECFB); $crypt->setKey($config->project->crypt_key); return $crypt; });

Session

$di->setShared('session', function() use($config) { $params = [];

if (!empty($config->project->sess_prefix)) {
    $params['uniqueId'] = $config->project->sess_prefix;
}

$session = new \Phalcon\Session\Adapter\Files($params);
$session->start();
return $session;

});

Flash messaging

$di->setShared('flash', function() { return new \Phalcon\Flash\Session([ 'error' => 'alert alert-danger', 'warning' => 'alert alert-warning', 'success' => 'alert alert-success', 'notice' => 'alert alert-info' ]); });

Config

$di->setShared('config', $config);<?php

Register DB

$di->setShared('mongo', function () use($config) { $mongo = new MongoClient('mongodb://mongo:27017'); return $mongo->selectDB($config->mongo->name); });

$di->setShared('collectionManager', function(){ return new Phalcon\Mvc\Collection\Manager(); });

Mailer (requires composer component)

$di->setShared('mailer', function () use($config) { $mailer = new \App\Lib\Mailer([ 'templates' => APP_PATH . 'common/emails/', 'host' => $config->smtp->host, 'port' => $config->smtp->port, 'username' => $config->smtp->username, 'password' => $config->smtp->password, 'security' => $config->smtp->security ]);

if (!empty($config->project->admin_email) && !empty($config->project->admin_name)) {
    $mailer->setFrom($config->project->admin_email, $config->project->admin_name);
}

return $mailer;

});

Logger

$di->setShared('logger', function() use($config, $di) { $logger = new \Phalcon\Logger\Multiple;

$logger->push(new \Phalcon\Logger\Adapter\File($config->project->log_path));
$logger->push(new \Phalcon\Logger\Adapter\Stream('php://stdout'));

return $logger;

});

$di->setShared('crypt', function() use($config) { $crypt = new \Phalcon\Crypt(); $crypt->setMode(MCRYPTMODECFB); $crypt->setKey($config->project->crypt_key); return $crypt; });

Session

$di->setShared('session', function() use($config) { $params = [];

if (!empty($config->project->sess_prefix)) {
    $params['uniqueId'] = $config->project->sess_prefix;
}

$session = new \Phalcon\Session\Adapter\Files($params);
$session->start();
return $session;

});

Flash messaging

$di->setShared('flash', function() { return new \Phalcon\Flash\Session([ 'error' => 'alert alert-danger', 'warning' => 'alert alert-warning', 'success' => 'alert alert-success', 'notice' => 'alert alert-info' ]); });

Config

$di->setShared('config', $config);


UnitTestCase.php

<?php use Phalcon\DI, \Phalcon\Test\UnitTestCase as PhalconTestCase;

abstract class UnitTestCase extends PhalconTestCase {

/**
 * @var \Voice\Cache
 */
protected $_cache;

/**
 * @var \Phalcon\Config
 */
protected $_config;

/**
 * @var bool
 */
private $_loaded = false;

public function setUp(Phalcon\DiInterface $di = NULL, Phalcon\Config $config = NULL) {

    // Load any additional services that might be required during testing
    $di = DI::getDefault();

    // get any DI components here. If you have a config, be sure to pass it to the parent
    parent::setUp($di);

    $this->_loaded = true;
}

/**
 * Check if the test case is setup properly
 * @throws \PHPUnit_Framework_IncompleteTestError;
 */
public function __destruct() {
    if(!$this->_loaded) {
        throw new \PHPUnit_Framework_IncompleteTestError('Please run parent::setUp().');
    }
}

}


and my test file

<?php

namespace Test;

/** * Class InvoiceTest */

class InvoiceTest extends \UnitTestCase {

//test mongo handler

/**
 * @dataProvider providerMongoAccount
 */
public function testMongoAccount($a)
{
    $testObject = new \App\Collections\Accounts();
    $testObject->createAccount($a);
    var_dump($testObject->_id); die;
}

public static function providerMongoAccount ()
{
    return array (
        array ('test1'),
        array ('test2'),
        array ('test3'),
        array ('test4'),
    );
}

}

and i get error

Phalcon\Di\Exception: Service 'collectionManager' wasn't found in the dependency injection container