My problem with PHPUnit is quite simple: if the test class file is included in the bootstrap file, PHPUnit won't be able to find the test class.
You can easily recreate the issue:
The file hierarchy:
./tests/MyTest.php
./bootstrap.php
./phpunit.xml
phpunit.xml
<phpunit bootstrap="./bootstrap.php">
<testsuites>
<testsuite name="MyTest">
<directory>./tests</directory>
</testsuite>
</testsuites>
</phpunit>
bootstrap.php:
<?php
require __DIR__ .'/vendor/autoload.php';
require __DIR__ .'/tests/MyTest.php';
tests/MyTest.php
<?php
namespace App\Tests;
use PHPUnit\Framework\TestCase;
class MyTest extends TestCase
{
public function testTrue()
{
$this->assertTrue(true);
}
}
In this case, when I run ./vendor/bin/phpunit, it returns "No tests executed!". And if I run ./vendor/bin/phpunit ./tests/MyTest.php, it returns "Class 'MyTest' could not be found in '[...]\tests\MyTest.php'.".
Now, if I remove the second require_once from autoload.php, both commands work as expected.
I've only seen a couple of similar issues on stack. They are six years old and have not been resolved, which makes me think that not allowing this way of loading classes is actually a design choice.
Could you please help me? Thank you!
Related
I'm trying to use PHPUnit in a PHP project.
Here is my project structure (files are in italic font style)
controllers
Pages.php
tests
pagesTest.php
vendor
bin
phpunit.bat
composer.json
My files:
composer.json
{
"require-dev": {
"phpunit/phpunit":"5.5.4"
}
}
Pages.php
<?php
namespace controllers
class Pages
{
public function render()
{
return 'Hello World';
}
}
pagesTest.php
<?php
class PagesTest extends PHPUnit_Framework_TestCase
{
public function testRenderReturnsHelloWorld()
{
$pages = new \controllers\Pages();
$expected = 'Hello Word';
$this->assertEquals($expected, $pages->render());
}
}
When I open the command line I write:
C:\xampp\htdocs\PHPUnitTestProject\vendor\bin>phpunit ../../tests/PagesTest.php
I receive this error message: PHP Fatal error: Class 'controllers\Pages' not found in C:\xampp\htdocs\PHPUnitTestProject\tests\pagesTest.php on line 7
It's a path problem. I think it's because it searches for C:\xampp\htdocs\PHPUnitTestProject\vendor\bin\controllers\Pages() which doesn't exists.
It should be C:\xampp\htdocs\PHPUnitTestProject\controllers\Pages()
You need to point to the tested class, so in pagesTest.php add a require:
require __DIR__ . "/../controllers/Pages.php";
Or if you are using autoloading, then you can bootstrap the autoload in your command line
phpunit --bootstrap src/autoload.php
Or you can set up a phpunit.xml configuration file like this example (from the PHPUnit page I linked to above):
<phpunit bootstrap="src/autoload.php">
<testsuites>
<testsuite name="money">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
Which you then use with the --configuration option.
Adding bootstrap="vendor/autoload.php" in phpunit.xml.dist solved the issue for me.
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"> <!-- in here -->
<php>
<!-- ... -->
</php>
<testsuites>
<!-- ... -->
</testsuites>
</phpunit>
Try composer dump-autoload -o command
Call phpunit from the root folder:
$ cd C:\xampp\htdocs\PHPUnitTestProject\
$ vendor\bin\phpunit tests/PagesTest.php
I was getting the same error because I hadn't named my Class the same as the filename that phpunit was calling.
e.g. I was calling:
phpunit TEST_myweb_controller.php
which had a class definition of: class web_controller_test extends PHPUnit\Framework\TestCase
This returned error: Class 'TEST_myweb_controller.php' could not be found in '\my\path\to\tests\TEST_myweb_controller.php'
To fix this I changed the class deinition to: class TEST_myweb_controller extends PHPUnit\Framework\TestCase
I'm new in PHPUnit and unit-testing, so I was install PHPUnit and phar via composer and everything had been going fine until I was try to start my simple test. I'm using PhpStorm where I can see all classes were autoload, but when I trying to start my test I got an error:
Fatal error: Class 'PharIo\Manifest\Simple' not found in C:\xampp\htdocs\mydocs\
I don't understand why he is looking for It in folder upper than PHPUnit is exists ?
I was trying to configure autoload section in composer.json and checking settings in phpunit.xml but nothing works.
Add:
I have to reinstall PHPUnit without PharIO, so now I have a little bit of progress, now I have a situation where I can test my class if I make require_once line with a name of the tested class. It looks like:
require_once '../src/Simple.php';
class SimpleTest extends PHPUnit_Framework_TestCase
{
public function testAdd() {
$sum = new Simple();
$this->assertEquals(5, $sum->add(2, 3));
}
}
So my simple class is:
class Simple {
public function add($a, $b) {
return (int) $a + (int) $b;
}
}
But, of course, I want to use namespaces. I try to make some changes based on this question: Autoloading classes in PHPUnit using Composer and autoload.php (I was try even use that repo for test, but an error is still exists) but nothing works for me. I was try to edit my autoload section in the composer.json like this
"autoload": {
"psr-4": {
"app\\": "src/"
}
},
But an error is still exists, another words autoload cannot see It. I was create phpunit.xml and phpunit.dist.xml with a same settings
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/3.7/phpunit.xsd"
backupGlobals="true"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="./tests/bootstrap.php">
<testsuites>
<testsuite name="The project's test suite">
<directory>./tests</directory>
</testsuite>
</testsuites>
</phpunit>
and I made tests/bootstrap.php too with
require_once '../vendor/autoload.php';
I know this is an old question, but maybe you need to do
composer dump-autoload for composer to generate the map of classes.
I wasted 30mins trying to understand why PHPUnit was giving me:
Cannot stub or mock class or interface XXX because it doesn't exists
You should specify the script with autoloading classes.
You can either specify the file with autoloading in XML-file, as suggested in the other answer, or just by specifying --bootstrap option in your command to run tests:
phpunit --bootstrap vendor/autoload.php tests
Composer's autoload relies on configuration located in the vendor/autoload.php file which needs to be loaded at some point in your execution thread. You application already includes this and that's why it works, but the tests use a different entry point so you need to configure it with a file called phpunit.xml.dist.
Assuming your file structure is something like:
app/
src/
tests/
bootstrap.php <- create it in your test folder
vendor/
...
composer.json
composer.lock
phpunit.xml.dist <- create it if does not exist
You can see the various options here, but for a basic config, you can use this.
File phpunit.xml.dist:
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/3.7/phpunit.xsd"
backupGlobals="true"
backupStaticAttributes="false"
bootstrap="tests/bootstrap.php">
</phpunit>
File tests/bootstrap.php:
require_once '../vendor/autoload.php';
You should run phpunit from the root.
I'm trying to use PHPUnit in a PHP project.
Here is my project structure (files are in italic font style)
controllers
Pages.php
tests
pagesTest.php
vendor
bin
phpunit.bat
composer.json
My files:
composer.json
{
"require-dev": {
"phpunit/phpunit":"5.5.4"
}
}
Pages.php
<?php
namespace controllers
class Pages
{
public function render()
{
return 'Hello World';
}
}
pagesTest.php
<?php
class PagesTest extends PHPUnit_Framework_TestCase
{
public function testRenderReturnsHelloWorld()
{
$pages = new \controllers\Pages();
$expected = 'Hello Word';
$this->assertEquals($expected, $pages->render());
}
}
When I open the command line I write:
C:\xampp\htdocs\PHPUnitTestProject\vendor\bin>phpunit ../../tests/PagesTest.php
I receive this error message: PHP Fatal error: Class 'controllers\Pages' not found in C:\xampp\htdocs\PHPUnitTestProject\tests\pagesTest.php on line 7
It's a path problem. I think it's because it searches for C:\xampp\htdocs\PHPUnitTestProject\vendor\bin\controllers\Pages() which doesn't exists.
It should be C:\xampp\htdocs\PHPUnitTestProject\controllers\Pages()
You need to point to the tested class, so in pagesTest.php add a require:
require __DIR__ . "/../controllers/Pages.php";
Or if you are using autoloading, then you can bootstrap the autoload in your command line
phpunit --bootstrap src/autoload.php
Or you can set up a phpunit.xml configuration file like this example (from the PHPUnit page I linked to above):
<phpunit bootstrap="src/autoload.php">
<testsuites>
<testsuite name="money">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
Which you then use with the --configuration option.
Adding bootstrap="vendor/autoload.php" in phpunit.xml.dist solved the issue for me.
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"> <!-- in here -->
<php>
<!-- ... -->
</php>
<testsuites>
<!-- ... -->
</testsuites>
</phpunit>
Try composer dump-autoload -o command
Call phpunit from the root folder:
$ cd C:\xampp\htdocs\PHPUnitTestProject\
$ vendor\bin\phpunit tests/PagesTest.php
I was getting the same error because I hadn't named my Class the same as the filename that phpunit was calling.
e.g. I was calling:
phpunit TEST_myweb_controller.php
which had a class definition of: class web_controller_test extends PHPUnit\Framework\TestCase
This returned error: Class 'TEST_myweb_controller.php' could not be found in '\my\path\to\tests\TEST_myweb_controller.php'
To fix this I changed the class deinition to: class TEST_myweb_controller extends PHPUnit\Framework\TestCase
Below are the paths where files are located,
src\TW\Talk\Entity\Talk.php
src\Tests\Talk\Entity\TalkTest.php
src\phpunit.xml.dist
In TalkTest.php, I have included PHPUnit and the entity Talk.
require_once 'TW/Talk/Entity/Talk.php';
require('PHPUnit/Autoload.php');
Class TalkTest extends PHPUnit_Framework_TestCase
{
...
}
In phpunit.xml.dist file, I have,
<phpunit>
<testsuites>
<testsuite name="TW">
<file>Tests/Talk/Entity/TalkTest.php</file>
</testsuite>
</testsuites>
</phpunit>
I am running phpunit command from src directory, I am getting error that Fatel Error: Class 'Tests\TW\Talk\Enity\Talk' not found.
For reference, I am referring to php-object-freezer-master which has similar structure.
Any idea why the TalkTest is not able to find Talk class ?
phpunit command is trying to find Talk entity in Tests folder.
Changing phpunit.xml.dist to
<phpunit bootstrap="loader.php">
<testsuites>
<testsuite name="TW_Talk">
<directory>Tests</directory>
</testsuite>
</testsuites>
</phpunit>
and loader file as,
<?php
function tw_test_autoloader($class) {
if(file_exists(__DIR__."\\" . $class . ".php"))
require_once(__DIR__."\\" . $class . ".php");
}
spl_autoload_register('tw_test_autoloader');
Worked for me.
But still if I replace directory tag to file
<file>Tests\TW\Talk\Entity\TalkTest.php</file>
It does not work.
Check your include_path:
echo get_include_path();
It should contain the directory to which your TW/Talk/Entity/Talk.php is relative. If it is not there, then you must add it either to php.ini or to PHPUnit's bootstrap.
You can easily test if PHP can find your file using your include path with this:
var_dump( stream_resolve_include_path('TW/Talk/Entity/Talk.php') );
I'm new to PHPUnit and am having some trouble setting it up to access my PHP files. The directory structure I'm using for my app is this:
./phpunit.xml
./lib/Application/
-> Dir1/File1.php (namespace = Application\Dir1)
-> Dir1/File2.php
-> Dir2/File1.php (namespace = Application\Dir2)
./tests/Application/Tests
-> Test1.php (namespace = Application\Tests)
-> Test2.php
In my PhpUnit.xml, I have:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit verbose="false">
<testsuites>
<testsuite name="Application">
<directory>./tests/Application/Tests</directory>
</testsuite>
</testsuites>
<logging>
<log type="coverage-text" target="php://stdout" showUncoveredFiles="false"/>
<log type="json" target="/tmp/phpunit-logfile.json"/>
</logging>
<filter>
<whitelist>
<directory suffix=".php">./lib</directory>
</whitelist>
</filter>
</phpunit>
And in one of my test files, I open with:
namespace Application\Tests;
use Application\Dir1\File1;
class MyTest extends File1 {}
But it keeps on saying:
Class 'Application\Dir1\File1' not found
Where am I going wrong?
If you installed PHPUnit using Composer then you can use Composers autoloader. The easiest way to do so would be to add:
"autoload":{
"psr-0":{
"your-app-directory":""
}
}
to composer.json
Even if you use use, you still have to include the file, either by using include, require, include_once, or require_once, or by using spl_autoload_register to include the file, like so:
spl_autoload_register(function ($class)
{
include '\lib\\' . $class . 'php';
});
When you then try to use Application\Dir1\File1 the script will automatically run include '\lib\Application\Dir1\File1.php'
I had the same issue.
I'm using composer as well and the only thing that solved it for me was the following:
add to your composer.json file in the autoload section a class map section with your root namespace
"autoload": {
"classmap": ["namespaceRoot/"]
}
execute composer dump-autoload command in order to recreate your autoload files (with all the class mappings!)
I found this really useful class autoloader by Jonathan Wage which allows PHPUnit tests to access namespaces from different directories. In my bootstrap.php, I just specified the location and associated module namespace:
require_once 'SplClassLoader.php';
$classLoader = new SplClassLoader('Application', dirname(__FILE__) . '/../lib');
$classLoader->register();