LoginSignup
0
0

More than 1 year has passed since last update.

【PHPUnit】factoryのリレーション先のデータ作成はafterCreatingを使おう

Posted at

環境

Laravel v9.5.1 (PHP v8.1.3)

状況

下記のようにテストでデータ作成していると、Userを削除したときのリレーション先のエラーが出ずテストでは動いているように見えていた。
だがこれに気づかないままデプロイしてdevelopでUserを削除した際、500エラーが起きてしまった。

class UserFactory extends Factory
{
  public function definition()
  {
    return [
      'name' => $this->faker->name(),
      'email' => $this->faker->unique()->safeEmail(),
      'avatar' => $this->faker->imageUrl(),
    ];
  }
}

class PointWalletFactory extends Factory
{
  public function definition(): array
  {
    return [
      'user_id' => User::factory(),
      'points' => 30,
    ];
  }
}

# test
User::factory()->create();
PointWallet::factory()->for($user)->create();
Illuminate\Database\QueryException
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails 

解決法

afterCreatingを使ってFactoryでUserを作成したときPointWalletも作成されるように追記。
するとUserを削除したときに先程のエラーが出るので、Userを削除したらリレーション先のPointWalletも削除されるようにmigrationファイルを書き換える。
さらに、PointWalletFactoryデータをテストのたびに作成しなくても良くなる。

class UserFactory extends Factory
{
  public function definition()
  {
    return [
      'name' => $this->faker->name(),
      'email' => $this->faker->unique()->safeEmail(),
      'avatar' => $this->faker->imageUrl(),
    ];
  }
 
  public function configure(): self
  {
    return $this->afterCreating(function (User $user) {
      PointWallet::factory()->for($user)->create();
    });
  }
}

class PointWalletFactory extends Factory
{
  public function definition(): array
  {
    return [
      'user_id' => User::factory(),
      'points' => 30,
    ];
  }
}

# test
User::factory()->create();
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0