I'm running into an issue when writing unit tests with PHPUnit using @dataProvider
in a Laravel app. The error I'm receiving is:
PHP Fatal error: Class 'Eloquent' not found in /path/to/project/app/models/ExampleClass.php on line 7
It looks like the constant used in the dataProvider
is causing the fatal.
composer.json:
"psr-4": {
"Acme\\Models\\": "app/models"
}
phpunit.xml:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="bootstrap/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
>
<testsuites>
<testsuite name="Application Test Suite">
<directory>./app/tests/</directory>
</testsuite>
</testsuites>
</phpunit>
The example model:
<?php
namespace Acme\Models;
use Eloquent;
class ExampleClass extends Eloquent
{
/**
* @var bool
*/
const TRUE = true;
}
The example test class:
<?php
use Acme\Models\ExampleClass;
class ExampleClassTest extends TestCase
{
/**
* Example test.
*
* @param int $value
* @return void
* @dataProvider testExampleTestDataProvider
*/
public function testExampleTest($value)
{
$this->assertTrue($value);
}
/**
* Data provider for testExampleTest.
*
* @return array
*/
public function testExampleTestDataProvider()
{
return array(
array(ExampleClass::TRUE),
);
}
}
Stack trace:
PHP Stack trace:
PHP 1. {main}() /usr/local/bin/phpunit:0
PHP 2. PHPUnit_TextUI_Command::main() /usr/local/bin/phpunit:612
PHP 3. PHPUnit_TextUI_Command->run() phar:///usr/local/bin/phpunit/phpunit/TextUI/Command.php:138
PHP 4. PHPUnit_TextUI_Command->handleArguments() phar:///usr/local/bin/phpunit/phpunit/TextUI/Command.php:148
PHP 5. PHPUnit_Util_Configuration->getTestSuiteConfiguration() phar:///usr/local/bin/phpunit/phpunit/TextUI/Command.php:696
PHP 6. PHPUnit_Util_Configuration->getTestSuite() phar:///usr/local/bin/phpunit/phpunit/Util/Configuration.php:837
PHP 7. PHPUnit_Framework_TestSuite->addTestFiles() phar:///usr/local/bin/phpunit/phpunit/Util/Configuration.php:924
PHP 8. PHPUnit_Framework_TestSuite->addTestFile() /path/to/project/vendor/phpunit/phpunit/src/Framework/TestSuite.php:400
PHP 9. PHPUnit_Framework_TestSuite->addTestSuite() /path/to/project/vendor/phpunit/phpunit/src/Framework/TestSuite.php:374
PHP 10. PHPUnit_Framework_TestSuite->__construct() /path/to/project/vendor/phpunit/phpunit/src/Framework/TestSuite.php:289
PHP 11. PHPUnit_Framework_TestSuite->addTestMethod() /path/to/project/vendor/phpunit/phpunit/src/Framework/TestSuite.php:188
PHP 12. PHPUnit_Framework_TestSuite::createTest() /path/to/project/vendor/phpunit/phpunit/src/Framework/TestSuite.php:842
PHP 13. PHPUnit_Util_Test::getProvidedData() /path/to/project/vendor/phpunit/phpunit/src/Framework/TestSuite.php:465
PHP 14. ReflectionMethod->invoke() /path/to/project/vendor/phpunit/phpunit/src/Util/Test.php:392
PHP 15. ExampleClassTest->testExampleTestDataProvider() /path/to/project/vendor/phpunit/phpunit/src/Util/Test.php:392
PHP 16. spl_autoload_call() /path/to/project/vendor/phpunit/phpunit/src/Util/Test.php:27
PHP 17. Composer\Autoload\ClassLoader->loadClass() /path/to/project/vendor/phpunit/phpunit/src/Util/Test.php:0
PHP 18. Composer\Autoload\includeFile() /path/to/project/vendor/composer/ClassLoader.php:278
PHP 19. include() /path/to/project/vendor/composer/ClassLoader.php:386
I'm having this exact issue. It has to do with the fact that the Laravel aliases (e.g. Config::
, Log::
...) have not been loaded at the time that the @dataProvider
method is called. There are two solutions here that I can think of here.
Solution 1
Modify your @dataProvider
so that it doesn't use the model class. In my case, I was creating model objects in the @dataProvider method, like this:
public function people() {
$person1 = new Person();
$person1->name = "me";
$person2 = new Person();
$person2->name = "you";
return [$person1, $person2];
}
Since the Person
class is referenced in the @dataProvider
method, it's going to attempt to load that class. Then it will fail because the Eloquent
class alias hasn't been created by Laravel yet.
To get around this, I could just return the data, and create the actual model objects in the test itself:
public function people() {
return ["me", "you"];
}
public function testPerson($name) {
$person = new Person();
$person->name = $name;
// Assertions...
}
In your case, that would mean returning [['true']]
, instead of [[ExampleClass::TRUE]]
.
Solution 2
I see no compelling reason to use the Eloquent
class alias here. In fact, I don't know why it exists at all (except perhaps that it "looks" better?). I brought this up in the IRC channel, and didn't get a response... So if there's a reason to use the alias here, then I don't know it.
That said, if your model class extends the underlying \Illuminate\Database\Eloquent\Model
class instead of the Eloquent
alias, then your tests will start working as-is.
<?php
namespace Acme\Models;
use \Illuminate\Database\Eloquent\Model;
class ExampleClass extends Model
{
/**
* @var bool
*/
const TRUE = true;
}
You have to run this in your dataProvider. As Thomas Kelley says this because it gets the dataProvider data before it have run CreateApplication code ether if you using that trait or you create application your self in the setUp method. This can also generate The data provider specified for x is invalid.
PHPStorm will only say No tests executed!
if a single test is run.
public function fooDataProvider() {
$this->refreshApplication();
//Code using laravel
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With