LaravelでRedisのテストにFaker(Factory)を使う

先生はfですか？zですか？

ヾ(・ω<)ﾉ"　三三三●　ⅱⅲ コロコロ♪

----
------------------- ↓ 余談はここから ↓-------------------

Laravelを使っていて、
CSVファイルをデータベースに登録する際、
一時的に利用するデータをテーブル創って入れていたのだが、
**Redisでよくね？**
と思い立ってしまった。

で、データベースのテストにはFactoryやSeedを使ってるわけだけど、
Redisでも使えるようにならんかなぁ :thinking: 
となったのでちょっとやってみた。

また、訳わからんこと。。。 :upside_down:


とりあえず動くレベルで、
形にはなったのでここに残しておこう。

Laravelのバージョンはこちら

```bash
$ php artisan --version
Laravel Framework 5.7.28
```

テーブル構造はこんな感じ

| item_name | item_num | item_price |
|:----------------:|:-----------------:|:------------------:|
| $faker->name | $fake->randomDigit | $fake->randomDigit |

ファイル構成はこんな感じ
全部ジェネレーターで作るので、
あらかじめ作っておく必要はない。

```bash
app/FakeModel.php
database/factories/FakeModelFactory.php
tests/Unit/FakeModelTest.php
```


`faker` を `fa●ker` と打ち間違える日々

----
------------------- ↓ 本題はここから ↓-------------------


## Factoryの生成

兎にも角にもFactoryを創る。
Factory名はFakeModelFactory。
モデルのクラス名をFakeModelとする。

```bash
$ php artisan make:model -f FakeModel         # モデルとfactory同時生成の場合
$ php artisan make:factory -m　FakeModel FakeModelFactory # factory単独の場合
```

#### factoryデータの調整

database/factories配下に指定したファイル名のfactoryが生成される。
これを実際の利用データの形に書き換えておく。

```php5:database/factories/FakeFactory.php
$factory->define(App\FakeModel::class, function (Faker $faker) {
    return [
        "item_name" => $faker->name,
        "item_num" => $faker->randomDigit,
        "item_price" => $faker->randomDigit,
    ];
});
```

## テストの生成

実行するテストを用意

```bash
$ php artisan make:test Units/FakeModelTest
```

```php5:tests/Unit/FakeModelTest.php
use Illuminate\Support\Facades\Redis;
use Symfony\Component\VarDumper\VarDumper;
use Faker\Factory as FakerFactory;  // ←↓名前かぶるのでalias
use Illuminate\Database\Eloquent\Factory as EloquentFactory;

class FakeModelTest extends TestCase
{
    public function FakeGenerator() {
        $class = FakeModel::class; // ←ここは自由なモデルに変更できる
        $attributes = [];          // ←factory()->createの引数
        $faker = FakerFactory::create();
        $factory = EloquentFactory::construct($faker)->load(database_path('factories'));
        $model = $factory->make($class, $attributes); // ←フェイクデータ入りモデル生成
        return $model->toArray();
    }

    public function testFake() {
        VarDumper::dump($this->FakeGenerator());
    }
}
```

これでテストランナーを走らせると、
適当データが出力されているはず。

```bash
$ ./vendor/bin/phpunit tests/Unit/FakeModelTest 
PHPUnit 6.5.14 by Sebastian Bergmann and contributors.
^ array:3 [
  "item_name" => "Lilla Howell"
  "item_num" => 3
  "item_price" => 8
]
```

:triumph:

テストランナーを叩く度に違うデータになる。
便利だな :no_mouth:

----
------------------- ↓ 後書はここから ↓-------------------

意外と簡単？ :thinking: 
内部を解析してコンパクトにまとめるのに丸一日かかったですよ。 :disappointed_relieved:

作ってみてわかったが。
フェイクデータ入りモデルが生成されるので、
苦労してモックを作らなくてもいいってことかな。
応用範囲は広そうだ。
ただ、当たり前だけどクエリビルダーとかは使えません。

タイトルのRedisが一個も出てこないじゃんと思われたかもだが、
ちゃんとテストをしている。

```php5:tests/Unit/FakeModelTest.php
//上記に追記
    public function testRedis(){
        $items = $this->FakeGenerator();

        $key = 'fake:item';
        Redis::hmset($key, array_values($items));
        var_dump(Redis::hgetall($key));
        Redis::del($key);
    }
```

Redisがdocker上にあるのでdocker経由でテストランナーを実行

```bash
$ docker-compose exec php-fpm vendor/bin/phpunit tests/Unit/FakeModelTest
R^ array:3 [
  0 => "Mr. Trent Kerluke"
  1 => "8"
  2 => "7"
]
```