I'm fairly new to unit testing, but I've read pretty much all the documentation on phpunit.de (Up to chapter 10).
It states that testing using databases can be slow, but if setup correctly, it can be just as fast as non-database testing.
As such, I want to test a model in Laravel. I've created a model factory to seed data into the database.
I've also created a basic test.
In PHPUnits documentation, it states that before every test, the setUp()
method is called to setup the test. There's also another static method setUpBeforeClass()
.
I want to seed my database table only once, and use the records within my test. So I used Laravels factory()
function to seed the database from within the setUpBeforeClass()
method.
This is my code:
class CommentTest extends TestCase
{
protected static $blog;
protected static $comments;
public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
self::$blog = factory(App\Models\Content\Blog::class)->create();
self::$comments = factory(App\Models\Content\Comment::class, 6)->create();
}
public function testSomething()
{
$this->assertTrue(true);
}
}
However, when I run phpunit
, I get the following error:
Fatal error: Call to a member function make() on a non-object in \vendor\laravel\framework\src\Illuminate\Foundation\helpers.php on line 54
Call Stack:
0.0002 240752 1. {main}() \vendor\phpunit\phpunit\phpunit:0
0.0173 1168632 2. PHPUnit_TextUI_Command::main() \vendor\phpunit\phpunit\phpunit:47
0.0173 1175304 3. PHPUnit_TextUI_Command->run() \vendor\phpunit\phpunit\src\TextUI\Command.php:100
2.9397 5869416 4. PHPUnit_TextUI_TestRunner->doRun() \vendor\phpunit\phpunit\src\TextUI\Command.php:149
2.9447 6077272 5. PHPUnit_Framework_TestSuite->run() \vendor\phpunit\phpunit\src\TextUI\TestRunner.php:440
2.9459 6092880 6. PHPUnit_Framework_TestSuite->run() \vendor\phpunit\phpunit\src\Framework\TestSuite.php:747
2.9555 6096160 7. call_user_func:{\vendor\phpunit\phpunit\src\Framework\TestSuite.php:697}() \vendor\phpunit\phpunit\src\Framework\TestSuite.php:697
2.9555 6096272 8. CommentTest::setUpBeforeClass() \vendor\phpunit\phpunit\src\Framework\TestSuite.php:697
2.9555 6096480 9. factory() \tests\CommentTest.php:18
2.9556 6096656 10. app() \vendor\laravel\framework\src\Illuminate\Foundation\helpers.php:350
If I move the code from setUpBeforeClass()
to setUp()
and run it, it works as expected, but surely this is inefficient as its seeding the database for every test?
My questions:
- Is seeding the database from within the
setUpBeforeClass()
the correct way to do this? - If it is (question 1), then why am I getting the fatal error when running phpunit, and is there anything I should be doing before calling
factory()
? - If I do have to place the code in the
setUp()
method, are there going to be performance issues? - Should I even be seeding from the
setUpBeforeClass()
orsetUp()
methods? In Laravels documentation it shows examples where the seeding is happening in the test itself, but If i'm running 100 tests (for example), is it a good idea to be seeding 100 times?