PHPUnit autoloader classes with composer - php

My project's structure is:
--/
--src
--tests
--phpunit.xml
--composer.json
I want to use composer for autoloading my classes from src folder in tests.
My composer.json:
{
"name": "codewars/pack",
"description": "Codewars project",
"type": "project",
"require": {
"fxp/composer-asset-plugin": "^1.2.0",
"phpunit/phpunit": "5.5.*",
"phpunit/dbunit": "2.0.*"
},
"autoload": {
"psr-4": {"Source\\": "src/"
}
}
}
Autoloder files generated:
<?php
// autoload_psr4.php #generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Source\\' => array($baseDir . '/src'),
);
My phpunit.xml:
<phpunit bootstrap="vendor/autoload.php">
<testsuites>
<testsuite name="Tests">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
And my test file example:
class Task2Test extends PHPUnit_Framework_TestCase
{
public function testTask2(){
$list=[1,3,5,9,11];
$this->assertEquals(7,\Source\findMissing($list));
$list=[1,5,7];
$this->assertEquals(3,\Source\findMissing($list));
}
}
And when I run tests I get error such as Fatal error: Call to undefined function Source\findMissing()
Please, help me, how can I solve this problem?

PSR-4 designed for autoloading classes, not for function. Because php cant find files with your functions.
May be better way write code with classes and static methods? Than you can use PSR-4 autoloading. Another way is specify "files" section into autoload section
{
"name": "codewars/pack",
"description": "Codewars project",
"type": "project",
"require": {
"fxp/composer-asset-plugin": "^1.2.0",
"phpunit/phpunit": "5.5.*",
"phpunit/dbunit": "2.0.*"
},
"autoload": {
"files": [
"src/my_cool_function1.php",
"src/my_cool_function2.php"
],
"psr-4": {
"Source\\": "src/"
}
}
For more information see this question

Related

Test class not found when extending abstract test class

I am currently using the lumen framework (v5.6) and writing unit tests for my code.
I have a base class TestCase:
namespace Tests;
$_SERVER["http_proxy"] = "";
abstract class TestCase extends \Laravel\Lumen\Testing\TestCase
{
/**
* Creates the application.
*
* #return \Laravel\Lumen\Application
*/
public function createApplication()
{
return require __DIR__.'/../bootstrap/app.php';
}
}
I use this base class to write my tests, however I have two tests with a lot of overlap (they both test implementations of an interface), so I put the common logic in an abstract class:
namespace Tests\App\IO;
use App\io\PageDataParser;
use App\Models\AdvancedArray;
use App\Services\PageService;
use Mockery;
use Tests\TestCase;
abstract class ParsePageDataTestCase extends TestCase
{
// Test logic here, but not relevant for the question
}
And finally I use this abstract class on my actual test:
namespace Tests\App\IO;
use App\io\JsonPageDataParser;
use App\Models\AdvancedArray;
class JsonParsePageDataTestCaseTest extends ParsePageDataTestCase
{
// Test are here, but not relevant for the question
}
However when I execute JsonParsePageDataTestCaseTest I get the following error:
PHP Fatal error: Class 'Tests\ParsePageDataTestCase' not found in \tests\app\io\JsonParsePageDataTest.php on line 15
I have verified that the structure of the folders is corrected, also tried using 'composer dump-autoloadand verified that mycomposer.jsonhas an entry which specifies a classmap to 'tests/.
I execute my tests using phpunit.xml which loads the bootstrap/app.php, but I still get this error.
The phpunit.xml:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="bootstrap/app.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Application test Suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
</whitelist>
</filter>
<php>
<!-- ENV variables go here -->
</php>
</phpunit>
And finally my composer.json:
{
"name": "laravel/lumen",
"description": "The Laravel Lumen Framework.",
"keywords": ["framework", "laravel", "lumen"],
"license": "MIT",
"type": "project",
"require": {
"php": ">=7.1.3",
"laravel/lumen-framework": "5.6.*",
"vlucas/phpdotenv": "~2.2",
"willdurand/hateoas": "~2.1",
"guzzlehttp/guzzle": "~6.0",
"ext-json": "*",
"vinelab/neoeloquent": "^1.4.6",
"jenssegers/mongodb": "3.4.*",
"predis/predis": "~1.0"
},
"require-dev": {
"fzaninotto/faker": "~1.4",
"phpunit/phpunit": "~7.0",
"mockery/mockery": "~1.0",
"barryvdh/laravel-ide-helper": "~2.5"
},
"autoload": {
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/"
}
},
"autoload-dev": {
"classmap": [
"tests/"
]
},
"scripts": {
"post-root-package-install": [
"#php -r \"file_exists('.env') || copy('.env.example', '.env');\""
]
},
"config": {
"preferred-install": "dist",
"sort-packages": true,
"optimize-autoloader": true
},
"minimum-stability": "dev",
"prefer-stable": true
}
If you need any more information please let me know.
Thank you in advance!
This is a problem from the Lumen installation.
When you install laravel the tests folder comes configured as psr-4 on autoload-dev:
{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"type": "project",
...
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
...
"minimum-stability": "dev",
"prefer-stable": true
}
But on Lumen installation doesn't as we can see bellow:
{
"name": "laravel/lumen",
"description": "The Laravel Lumen Framework.",
"keywords": ["framework", "laravel", "lumen"],
"license": "MIT",
"type": "project",
"require": {
"php": ">=7.1.3",
"laravel/lumen-framework": "5.7.*",
"vlucas/phpdotenv": "~2.2"
},
"require-dev": {
"fzaninotto/faker": "~1.4",
"phpunit/phpunit": "~7.0",
"mockery/mockery": "~1.0"
},
"autoload": {
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/"
}
},
"autoload-dev": {
"classmap": [
"tests/"
]
},
"scripts": {
"post-root-package-install": [
"#php -r \"file_exists('.env') || copy('.env.example', '.env');\""
]
},
"config": {
"preferred-install": "dist",
"sort-packages": true,
"optimize-autoloader": true
},
"minimum-stability": "dev",
"prefer-stable": true
}
So in order for this to work you will need to change the autoload to:
"autoload-dev": {
"classmap": [
"tests/"
],
"psr-4": {
"Tests\\": "tests/"
}
}

Fatal error when instanciating Pusher - Can't find class

I have a project to test and play around, with the following structure:
app/
controllers/
HomeController.php
handlers/
models/
vendor/
composer/
psr/
pusher/
pusher-php-server/
src/
Pusher.php
PusherException.php
PusherInstance.php
tests/
composer.json
autoload.php
index.php
I tried to require the Pusher autoloader in my index file:
require 'vendor/autoload.php';
Which is the following:
// autoload.php #generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInite16b90ab01042d2a69b1d54243c9e23a::getLoader();
Now, in my HomeController.php, I have the following code:
namespace App\controllers;
use \App\handlers\Views as View;
use \App\models\Home_model as Home;
use \App\controllers\SessionController;
use \Pusher\Pusher as Pusher;
class HomeController {
private $pusher;
public function __construct() {
$options = array(
'cluster' => 'hmm',
'encrypted' => true
);
$this->pusher = new Pusher(
'secret',
'secret',
'secret',
$options
);
}
public function index() {
$data['message'] = 'hello world';
$this->pusher->trigger('my-channel', 'my-event', $data);
return $this->view->render('views/home/index.php');
}
}
But this returns me an error:
Fatal error: Class 'Pusher\Pusher' not found in
And I'm not sure what I'm doing wrong. Could someone explain me what I'm doing wrong?
In composer.json I get the following:
{
"name": "pusher/pusher-php-server",
"description" : "Library for interacting with the Pusher REST API",
"keywords": ["php-pusher-server", "pusher", "rest", "realtime", "real-time", "real time", "messaging", "push", "trigger", "publish", "events"],
"license": "MIT",
"require": {
"php": "^5.4 || ^7.0",
"ext-curl": "*",
"psr/log": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8 || ^5.7"
},
"autoload": {
"psr-4": {
"Pusher\\": "src/"
}
},
"autoload-dev": {
"psr-4": { "": "tests/" }
},
"config": {
"preferred-install": "dist"
},
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"minimum-stability": "dev",
"prefer-stable": true
}
On Github, they mention that the library depends on cURL and JSON modules.
Not realy sure if this has something to do with my issue?
I'm still stuck, so any help is greatly appreciated.
Also, I'm using a .htaccess file, to rewrite my urls.
I have managed your code to work with right composer.json next to index.php:
{
"name": "awesome/project",
"type": "project",
"license": "MIT",
"authors": [
{
"name": "Author",
"email": "author#gmail.com"
}
],
"autoload": {
"psr-4": {
"": ""
}
},
"require": {
"pusher/pusher-php-server": "dev-master"
}
}
Then just run composer install.
My index.php contents:
<?php
require 'vendor/autoload.php';
use app\controllers\HomeController;
$ctrl = new HomeController();

PSR-4 autoloading with Composer - Class not found

I'm create composer package with type library. And trying to require it to Symfony2 project.
The package has following composer.json
{
"name": "vendor/package-sdk",
"description": "My private package",
"type": "library",
"license": "MIT",
"autoload": {
"psr-4": {"Vendor\\PackageSDK\\": "src/"}
},
"require": {
"php": ">=5.3.3"
}
}
Then I require it to my SF2 project.
"repositories": [
{
"type": "git",
"url": "git#github.com:me/vendor-package-sdk.git"
},
],
"require": {
...
"vendor/package-sdk": "~0.0.1-alpha1"
...
}
When I calling
use Vendor\PackageSDK\Client;
...
$client = new Client();
```
And I got fatal error:
PHP Fatal error: Class 'Vendor\PackageSDK\Client' not found in /path
If I do
composer dump-autoload -o
It works, but
composer dump-autoload
not.
The file vendor/composer/autoload_psr4.php contain:
'Vendor\\PackageSDK\\' => array($vendorDir . '/vendor/package-sdk/src'),
Could anybody tell me what am I doing wrong?
In composer autoload_classmap.php file I saw the following line
'Vendor\PackageSDK\Client' => $vendorDir . '/vendor/package-sdk/src/Cilent.php',
So it's just a typo in filename of package
Cilent.php should be Client.php

Composer create local package

In my project inside the vendor directory I created a new directory named Hello and created a new class HelloWorld.php with the namespace Hello\Test. Then in the root of Hello I created a composer.json with default meta data (author, license, desc, required), and added autoload PSR-4 Hello\\Test\\.
So what do I need to do next to autoload my package. I looked at some Symfony components and their composer.json package and configuration is the same.
Is it possible to autoload my local package from vendor like this?
Dir structure:
|-my_project
|-composer.json
|---vendor
|-------composer
|-------autoload.php
|-------Hello
|-----------composer.json
|-----------HelloWorld.php
./vendor/Hello/composer.json
{
"name": "Zend/Hello",
"description": "My test package",
"license": "MIT",
"authors": [
{
"name": "Zend Zend",
"email": "test#example.com"
}
],
"autoload": {
"psr-4": {
"Hello\\Test\\": ""
}
}
}
My HelloWorld.php class has namespace Hello\Test;
Inside index.php i do include 'vendor/autoload.php
And root composer.json
{
"autoload": {
"psr-4": {
"": "src/",
"Hello\\Test\\": "./vendor/Hello"
}
},
"require": {
"Hello/Test": "*"
}
}
composer update
Okay! Sorry for the late reply.
You only need one composer.json to make this work. The one in your main project directory.
Try using this:
{
"name": "Zend/Hello",
"description": "My test package",
"license": "MIT",
"authors": [
{
"name": "Zend Zend",
"email": "test#example.com"
}
],
"autoload": {
"psr-4": {
"Hello\\Test\\": "vendor/Hello"
}
}
}
And your HelloWorld.php file should be like:
<?php
namespace Hello\Test;
class HelloWorld {
// your methods goes here
}
Run a composer self update to get the latest composer the run composer update and it should now be added to your vendor/composer/autoload_psr4.php file

Composer doesnt update autoload namespace

Composer not updating autoload_namespaces.php file, despite downloading package normaly. Can't understand where i did a mistake.
If i load something from packagist, namespaces file updating successfully.
Project structure
Main Composer.json
{
"repositories":[
{
"type": "package",
"package": {
"name": "test/framework",
"version": "1.0.0.1",
"dist": {
"url": "http://localhost/repo/1.zip",
"type": "zip"
}
}
}
],
"require": {
"test/framework": "*"
}
}
Package composer.json
{
"name": "test/framework",
"type": "library",
"require": {
"php": ">=5.2.4"
},
"autoload": {
"psr-0" : {
"Test" : "lib/"
}
}
}
autoload_namespaces.php
<?php
// autoload_namespaces.php #generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);
You are downloading the package defined in the repositories via zip.
https://getcomposer.org/doc/05-repositories.md#package-2
In this case I feel you should define the package definition at the same place. See the above link for the example which contains autoload definition defined.
{
"repositories":[
{
"type": "package",
"package": {
"name": "test/framework",
"version": "1.0.0.1",
"dist": {
"url": "http://localhost/repo/1.zip",
"type": "zip"
},
"autoload": {
"psr-4" : {
"Test\\": "lib"
}
}
}
}
],
"require": {
"test/framework": "*"
}
}
You can also try some variation see my post over http://harikt.com/blog/2014/05/29/hidden-gems-of-composer/
PS : psr-4 is the recommended way for it can autoload psr-0 structured classes. See https://getcomposer.org/doc/04-schema.md#autoload
Just to add to what Hari K T said, be sure to remove the vendor directory after making an update to the composer.json file as composer uses the installed.json file in the ./vendor/composer directory to generate the autoload php files.
I had setup the composer.json correctly, but did not remove the existing vendor directory, so I assumed the answer provided by Hari K T didn't work.

Categories