37
loading...
This website collects cookies to deliver better user experience
// database/factories/PostFactory.php
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use App\Post;
use Faker\Generator as Faker;
$factory->define(Post::class, function (Faker $faker) {
return [
'title' => $faker->words(3, true),
'content' => $faker->text,
'author_id' => factory(User::class),
'publish' => false,
];
});
$factory->state(Post::class, 'published', function (Faker $faker) {
return [
'publish' => true,
]
});
// tests/Unit/PostTest.php
<?php
namespace Tests\Unit;
use App\Post;
use Tests\TestCase;
class PostTest extends TestCase
{
public function test_post_is_not_published()
{
$post = factory(Post::class)->make();
$this->assertFalse($post->published);
}
public function test_published_post_is_published()
{
$post = factory(Post::class)->state('published')->make();
$this->assertTrue($post->published);
}
}
@var
declaration and replace it with a namespace.// Remove
/** @var \Illuminate\Database\Eloquent\Factory $factory */
// Add
namespace Database\Factories;
Illuminate\Database\Eloquent\Factories\Factory;
and not the old factory Illuminate\Database\Eloquent\Factory
. This caught me out more than once.<?php
namespace Database\Factories;
use App\Post;
use Faker\Generator as Faker;
use Illuminate\Database\Eloquent\Factories\Factory;
class PostFactory extends Factory
{
protected $model = Post::class;
}
fzaninotto/Faker
in your composer.json file, which is now archived. Take this opportunity to update your composer.json to use fakerphp/faker
and run composer update
.$this->faker
from the parent Factory class. This means we can also remove the following line.// Remove
use Faker\Generator as Faker;
definition
method on the class.$faker
to $this->faker
.factory()
helper, from factory(User::class)
to User::factory()
. This means that we will also have to update the UserFactory.php to use the new class based approach.public function definition()
{
return [
'title' => $this->faker->words(3, true),
'content' => $this->faker->text,
'author_id' => User::factory()),
'publish' => false,
];
}
$factory->state()
syntax. Now we can create a new method on the class which returns $this->state()
.public function published()
{
return $this->state(function (array $attributes) {
return [
'publish' => true,
]
});
}
<?php
namespace App\Post;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
}
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
},
composer dump-autoload
to update the autoloader.factory()
helper and use the Model::factory()
syntax instead. So factory(Post::class)
becomes Post::factory()
.factory(Post::class)->state('published')
becomes Post::factory()->published()
.// tests/Unit/PostTest.php
<?php
namespace Tests\Unit;
use App\Post;
use Tests\TestCase;
class PostTest extends TestCase
{
public function test_post_is_not_published()
{
$post = Post::factory()->make();
$this-assertFalse($post->published);
}
public function test_published_post_is_published()
{
$post = Post::factory()->published()->make();
$this-assertTrue($post->published);
}
}
Replace in files
function is very useful replacing factory(Post::class)
with Post::factory()
over many files.->state('published')
to ->published()
. To be honest, I ended up changing the states manually.factory(Post::class, 3)
to Post::factory()->count(3)
.