Factoryクラスに何も書かなくてもいいケース

## はじめに
Laravelでテストを実装中に「Class "Database\Factories\MessageRoomFactory" not found」というエラーに遭遇しました。

今回は、database/factoriesに新しくMessageRoomFactoryクラスを作成することで対処ができました。」

https://readouble.com/laravel/10.x/ja/eloquent-factories.html

## 環境
Laravel 9.52.16

## 問題
* 次のようなテストを実行したい

```php: MessagesControllerTest.php（該当メソッドのみ）
public function test_Messages_store()
    {
        // テストユーザを作成
        $user = User::factory()->create();
        // メッセージルームを作成
        $message_room = MessageRoom::factory()->create();

        // テスト用のフォームデータを作成
        $formData = [
            'message' => 'テストメッセージ',
        ];

        // 作成したユーザでアクセス
        $response = $this->actingAs($user)->post('/my/messages/store/' . $message_room->id, $formData);

        $response->assertStatus(302);
        $this->assertDatabaseHas('messages', [
            'message' => $formData['message'],
            'message_room_id' => $message_room->id,
            'user_id' => $user->id,
        ]);


    }
```

* しかし実行すると次のようなエラーが出る

```php 
root@:/var/www/html/niches# php artisan test --filter MessagesControllerTest      

Deprecated: PHP Startup: Use of mbstring.internal_encoding is deprecated in Unknown on line 0

Deprecated: PHP Startup: Use of mbstring.internal_encoding is deprecated in Unknown on line 0

   FAIL  Tests\Feature\Http\Controllers\MessagesControllerTest
   
  ⨯ messages store

  ---

  • Tests\Feature\Http\Controllers\MessagesControllerTest > messages store
   PHPUnit\Framework\ExceptionWrapper 

  Class "Database\Factories\MessageRoomFactory" not found

  at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:821
    817▕     public static function factoryForModel(string $modelName)
    818▕     {
    819▕         $factory = static::resolveFactoryName($modelName);
    820▕
  ➜ 821▕         return $factory::new();
    822▕     }
    823▕
    824▕     /**
    825▕      * Specify the callback that should be invoked to guess factory names based on dynamic relationship names.


  Tests:  1 failed
  Time:   15.79s
```

「クラス"Database\Factories\MessageRoomFactory"が見つかりません」とのこと。

## 解決法
* database/factoriesを確認してみると、確かにMesssageRoomFactoryがなかった
* これにより、テストレコードを作成するためのfactory()メソッドが使えなかったっぽい
* database/factoriesにMessageRoomFactoryクラスを追加する

```php: database/factories/MessageRoomFactory.php
<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\MessageRoom>
 */
class MessageRoomFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */

    public function definition()
    {
        return [
            
        ];
    }
}
```

```php
root@:/var/www/html/niches# php artisan test --filter MessagesControllerTest

Deprecated: PHP Startup: Use of mbstring.internal_encoding is deprecated in Unknown on line 0

Deprecated: PHP Startup: Use of mbstring.internal_encoding is deprecated in Unknown on line 0

   PASS  Tests\Feature\Http\Controllers\MessagesControllerTest

  ✓ messages store

  Tests:  1 passed
  Time:   12.13s
```

これで無事解決です！

## 補足
通常、Factoryにはテスト用のデフォルト値を設定しなければいけません。

しかし今回はテーブルが'id'、'timestamps'のみであり、Eloquentが勝手に補完してくれるので、空でも問題ありません。

```sql
mysql> desc message_rooms;
+------------+-----------------+------+-----+---------+----------------+
| Field      | Type            | Null | Key | Default | Extra          |
+------------+-----------------+------+-----+---------+----------------+
| id         | bigint unsigned | NO   | PRI | NULL    | auto_increment |
| created_at | timestamp       | YES  |     | NULL    |                |
| updated_at | timestamp       | YES  |     | NULL    |                |
+------------+-----------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
```

まず、主キーである'id'カラムは自動インクリメントにより値を指定する必要がありません。

また、'created_at'と'updated_at'はEloquentモデルが自動的に埋めてくれます。

https://readouble.com/laravel/8.x/ja/eloquent.html

よって今回のケースでは、フィールドを定義する必要がありません。

```php: database/factories/MessageRoomFactory.php
<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\MessageRoom>
 */
class MessageRoomFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */

    public function definition()
    {
        // 今回はフィールドを定義する必要はなし
        return [
            
        ];
    }
}
```

## おわりに
なんとなくFactoryクラスはモデルとセットで生成されると勘違いしていましたが、どうやら違うようでした。

やはりテストをする時にはFactoryクラスを使うのが便利ですね！

## 参考
https://readouble.com/laravel/10.x/ja/eloquent-factories.html

https://readouble.com/laravel/8.x/ja/eloquent.html

https://qiita.com/yuto-hatano/items/8d82cc17f0350d31a901