Included class inside a PHPUnit file can't use Autoloader? - php

I have write a router.test.php file:
class RouterTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
require_once '../router.class.php';
}
public function testUnit()
{
$this->assertEquals(true, true);
}
}
... for simply test if my PHPUnit library is working correctly. But when I type phpunit router.test.php in my console I get this error message: Fatal error: Trait 'Core' not found in C:\xampp\htdocs\_Framework\ver_3\libraries\router\router.class.php on line 23
... my Router class is working correctly and my Autoloader automatically include trait (named Core) inside my Router class.
Where is the problem?
My Autoloader register method looks like:
public static function register()
{
return spl_autoload_register(
__CLASS__ . '::load'
);
}
... I use this method in my index.php file, should I write another autoloader for PHPUnits?
I have include necessary files in the setUp method, now the class looks like that:
<?php
use Framework\Libraries\Configuration\Configuration;
use Framework\Libraries\Autoload\Autoloader;
class RouterTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
require '../../core.trait.php';
require '../../configuration/configuration.class.php';
require '../../autoload/autoloader.class.php';
Configuration::set('files', [
require '../../../configuration/framework.configuration.php',
require '../../../configuration/autoloader.configuration.php',
require '../../../configuration/router.configuration.php',
]);
Autoloader::set('prefixes', ['Framework']);
Autoloader::set('extensions', ['.class.php', '.trait.php']);
Autoloader::register();
require_once '../router.class.php';
}
public function testUnit()
{
$this->assertEquals(true, true);
}
}
... an I get a new error message: E Time: 109 ms, Memory: 1.75Mb There was 1 error, but I can't get the error message. I think it's because Autoloader can't load files because of wrong path.

No it won't load index file automatically. So you need to include all your relevant class in your unit test class by adding include_once('AutoLoader.php'); in or another way is to create a bootstrap.php file & include all classes you need in all the PHPUnit Test class.
Reference.

Related

PHP Undefined variable: templates in Controller

I have this folder structure for mvc:
application
-----------catalog
------------------controller
----------------------------IndexContoller.php
------------------model
----------------------------IndexModel.php
------------------view
------------------language
-----------admin
------------------controller
------------------model
------------------view
------------------language
core
------Controller.php
public
------Index.php
vendor
....
In index.php I have:
define('DS', DIRECTORY_SEPARATOR, true);
define('BASE_PATH', __DIR__ . DS, TRUE);
//Show errors
//===================================
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
define('ABSPATHS', preg_replace('/\\\/', '/', dirname(dirname(__FILE__))));
$abspath = preg_replace('/\\\/', '/', dirname(__FILE__));
require '../vendor/autoload.php';
//Upadte
$templates = new League\Plates\Engine(Config::get('PATH_VIEW'));
and autoload using composer PSR4 like this :
"autoload": {
"psr-4": { "Application\\": "application/","Application\\Core\\": "application/core/","Application\\Catalog\\Model\\": "application/catalog/model/"}
}
}
Now in Core Controller I have:
namespace Application\Core;
class Controller
{
// public $templates;
/**
* Construct the (base) controller. This happens when a real controller is constructed, like in
* the constructor of IndexController when it says: parent::__construct();
*/
public function __construct()
{
$this->Language = new Language();
}
}
In controller IndexController I have:
namespace Application\Catalog\Controller;
use Application\Core\Controller as Controller;
class IndexController extends Controller
{
/**
* Construct this object by extending the basic Controller class
*/
public function __construct()
{
parent::__construct();
}
/**
* Handles what happens when user moves to URL/index/index - or - as this is the default controller, also
* when user moves to /index or enter your application at base level
*/
public function index()
{
echo $templates->render('index/index', ['name' => 'Jonathan']);
}
}
In Action i see this error and autoload not loading class in controller:
Notice: Undefined variable: templates in /Applications/XAMPP/xamppfiles/htdocs/cms/application/catalog/controller/IndexController.php on line 23
How do can i fix this error?
The error states that Application\Core\League\Plates\Engine can not be found. According to your autoload definition Application\Core is located at application/core but according to you directory structure you supplied that file doesn't exists. You need to ensure the file you're trying to load exists where you've said it is.
As a side note you're using composer's PSR-4 autoload functionality but you aren't conforming to PSR-4
You're not explicitly listing vendor folder contents, but I suppose you installed the package https://github.com/thephpleague/plates/blob/master/composer.json through composer... then:
How about placing in Controller :
/Applications/XAMPP/xamppfiles/htdocs/cms/application/core/Controller.php
on top the line:
use League\Plates\Engine;
Also:
"autoload": {
"psr-4": { "Application\\": "application/","Application\\Core\\": "application/core/","Application\\Catalog\\Model\\": "application/catalog/model/"}
}
}
is too much...
The following should be enough:
autoload": {
"psr-4": {
"Application\\": "application/"
}
}
Then add directives like (when needed) in your classes:
use Application\Catalog\Model\...
EDIT
Var $templates is not accessible within IndexController, try this:
remove form index.php
$templates = new League\Plates\Engine(Config::get('PATH_VIEW'));
and edit IndexController as follows:
namespace Application\Catalog\Controller;
use Application\Core\Controller as Controller;
use League\Plates\Engine;
class IndexController extends Controller
{
/**
* Construct this object by extending the basic Controller class
*/
public function __construct()
{
parent::__construct();
}
/**
* Handles what happens when user moves to URL/index/index - or - as this is the default controller, also
* when user moves to /index or enter your application at base level
*/
public function index()
{
$templates = new Engine(Config::get('PATH_VIEW'));
echo $templates->render('index/index', ['name' => 'Jonathan']);
}
}
But since I suppose you'll need to use $templates in more controllers you should define
protected $templates = new League\Plates\Engine(Config::get('PATH_VIEW'));
in parent class Controller and access to it through
$this->templates
in descendants...

Understanding php namespace and why the fatal error: undefined constant

Trying to understand how namespace in php works and am stuck.
This below is the architecture of the project.
Class: Loader.php (suppose to load controller/model/ library but for now gibberish test codes)
namespace system\core;
class Loader
{
public function index()
{
echo 'loader';
}
public function controller($pathtocontroller)
{
// Echo path to the controller
echo $pathtocontroller;
}
}
index.php
require 'system/core/Loader.php';
require 'system/core/BaseController.php';
require 'app/controller/common/HomeController.php';
use system\core;
use app\controller;
$loader = new \system\core\Loader();
$loader->controller(app\controller\common\HomeController);
and this is the error I get
Fatal error: Undefined constant 'app\controller\common\HomeController'
in C:\xampp\htdocs\psrstd\index.php on line 20. Lin 20 on index is $loader->controller(app\controller\common\HomeController);
Expected Result: app/controller/common/HomeController
in case you wondering what's in there at the HomeController (again gibberish test code)
namespace app\controller\common;
use system\core\BaseController;
class HomeController extends BaseController
{
public function index()
{
echo 'home';
}
}
you are passing a constant type to your controller method,
you are aiming to pass an object [ dependency injection ] so you will need to instantiate your argument like :
$loader->controller(new \app\controller\common\HomeController);
otherwise you may send this argument as a string like :
$loader->controller("\\app\\controller\\common\\HomeController");
and instantiate that object within your method [ as a factory method ]
public function controller($pathtocontroller)
{
// new $pathtocontroller and so on
}
Further reading :
What is Dependency Injection?
Factory design pattern

Config class not found when unit testing laravel package

I'm working on a Laravel (5.4) package, and I'm trying to do unit testing. I have this class :
<?php
namespace Sample;
class Foo
{
public function getConfig()
{
$config = \Config::get('test');
return $config;
}
}
I have this test :
<?php
use PHPUnit\Framework\TestCase;
use Sample\Foo;
class FooTest extends TestCase
{
public function testGetConfig()
{
$foo = new Foo;
$config = $foo->getConfig();
}
}
When I execute phpunit I have this error :
Error: Class 'Config' not found
How can I unit test this class ?
Thank you.
Instead of extends PHPUnit\Framework\TestCase, you should extends Tests\TestCase:
<?php
namespace Tests\Unit;
// use PHPUnit\Framework\TestCase;
use Tests\TestCase;
use Sample\Foo;
class FooTest extends TestCase
{
public function testGetConfig()
{
$foo = new Foo;
$config = $foo->getConfig();
}
}
Moreover, Config or other Laravel facades may not work in #dataProvider method, please see Laravel framework classes not available in PHPUnit data provider for more info.
It is good practice to mock the dependencies in your code. In this case you are depending on an outside class (Config). Usually I test it like this:
// make sure the mock config facade receives the request and returns something
Config::shouldReceive('get')->with('test')->once()->andReturn('bla');
// check if the value is returned by your getConfig().
$this->assertEquals('bla', $config);
Obviously, you need to import the Config facade in your test.
BUT: I would inject the Config class in the constructor in my real code, instead of using the facade. But that's me... :-)
Something like this
class Foo
{
/** container for injection */
private $config;
public function __construct(Config config) {
$this->config = $config;
}
public function getConfig()
{
$config = $this->config->get('test');
return $config;
}
}
And then test it by injecting a mock Config into the constructor.
Try by including like this
use Illuminate\Support\Facades\Config;

PhalconPHP - Unable to load a component from the DI in a controller

I am trying to create an ACL component as a service, for a multi-module PhalconPHP application. When I call the ACL component from the Controller Base, I am getting an error that I can't re-declare the ACL class.
Any ideas how to fix it, and understand the logic of why it is re-initialized again?
Fatal error: Cannot declare class X\Acl\Acl because the name is already in use in C:\xampp\htdocs\x\app\common\Acl\Acl.php on line 12
Update:
If I changed everything to "Pacl" then it works. I assume there might be a mixup with the PhalconPHP namespace. I am either not using the namespaces properly, or there's a bug in PhalconPHP 2.1 Beta 2.
/app/common/Acl/Acl.php
namespace X\Acl;
use Phalcon\Mvc\User\Component;
use Phalcon\Acl;
use Phalcon\Acl\Role as AclRole;
use Phalcon\Acl\Resource as AclResource;
/*
* ACL component
*/
class Acl extends Component {
private function initialize() {
}
public function isAllowed() {
die('called');
}
}
/app/front/controllers/ControllerBase.php
namespace X\Front\Controllers;
use Phalcon\Session as Session;
use Phalcon\Mvc\Controller;
use Phalcon\Mvc\Dispatcher;
class ControllerBase extends Controller {
public function beforeExecuteRoute(Dispatcher $dispatcher) {
//$this->acl = $this->getDI()->get("acl");
var_dump($this->acl->isAllowed()); //same behavior in both case
}
}
/app/front/Module.php
namespace X\Front;
use Phalcon\DiInterface;
use Phalcon\Mvc\Dispatcher;
use X\Acl\Acl as Acl;
class Module {
public function registerAutoloaders() {
$loader = new \Phalcon\Loader();
$loader->registerNamespaces(array(
'X\Front\Controllers' => __DIR__ . '/controllers/',
'X\Front' => __DIR__,
'X' => __DIR__ . '/../common/'
));
$loader->register();
}
public function registerServices(DiInterface $di) {
$di['acl'] = function() {
return new Acl();
};
}
}
This is not Phalcon issue. Look closely at your code:
namespace X\Acl;
use Phalcon\Acl;
class Acl extends ... {
}
What Acl interpreter should use? X\Acl\Acl or Phalcon\Acl?
The same error you get for example for the following code
namespace My\Awesome\Ns;
use Some\Name; # Name 1
class Name # Name 2
{
}

Class not found in path

So I have php project and when I'm running the tests the class TestCase isn't found and I can't figure out why. The error in question is this: Fatal error: Class 'project\Tests\Api\TestCase' not found in /some/path/here/test/project/Tests/Api/UsersTest.php on line 6
The below file is named UsersTest.php and TestCase is the class that can't be found.
<?php
namespace project\Tests\Api;
class UsersTest extends TestCase
{
// code here
}
The below file is TestCase.php which exists in the same folder as UsersTest.php
<?php
namespace project\Tests\Api;
abstract class TestCase extends \PHPUnit_Framework_TestCase
{
abstract protected function getApiClass();
protected function getApiMock()
{
// code here
}
}
Both of these files exists in a folder structure test/project/Tests/Api/. From my understanding UsersTest.php should be able to find the class because both of these files exist in the same namespace.
In test/project I have bootstrap.php file that looks like this.
<?php
function includeIfExists($file)
{
if (file_exists($file)) {
return include $file;
}
}
if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../.composer/autoload.php'))) {
die('You must set up the project dependencies, run the following commands:'.PHP_EOL.
'curl -s http://getcomposer.org/installer | php'.PHP_EOL.
'php composer.phar install'.PHP_EOL);
}
$loader->add('project\Tests', __DIR__);
return $loader;

Categories