UploadedFile::fake()->image()を使うとCIでのみエラーが出る


問題

GitLab RunnerでUploadedfile::fake()->image()を使ったユニットテストを
走らせると以下のようなエラーが出ました。
(ローカルではエラーなく通っています。)

TypeError: call_user_func(): Argument #1 ($callback) must be a valid callback, function “imagejpeg” not found or invalid function name

要約すると、以下の通りです。
call_user_func()の第一引数には有効なコールバック関数を渡してください。
"imagejpeg"なんて名前の関数は存在していないか有効ではありません。

この原因の詳しい説明については以下の記事をご覧ください。
Laravelのバージョンアップにて一部メソッドの挙動が変更されたことが原因だそうです。

解決策

解決策は、以下の通りです。

  1. libpng-dev libjpeg-dev をパッケージマネージャー(apt-get, yum)でインストール
  2. gdの拡張機能の設定をするときに適切なオプションを追加

2の手順に関しては、PHPのバージョンによってオプションが少し異なります。

1. libpng-dev, libjpeg-dev

RUN apt-get update && apt-get install -y libjpeg-dev libpng-dev

2. gd環境設定

PHP7.3 or below

RUN docker-php-ext-configure gd --with-gd --with-jpeg-dir --with-png-dir

PHP7.4 or above

RUN docker-php-ext-configure gd --enable-gd --with-jpeg

余談

この問題を発見、解決するまでに時間がかかりました。
なぜなら、この問題が起きた状態でGitLab Runner上でユニットテストを一括実行しようとすると
PHPUnitが多重起動しました。
その際、エラーメッセージも何も表示されず、ただPHPUnitが起動・終了を繰り返すばかりで
最後はCIのログ容量がいっぱいになり、強制終了するという挙動だったからです。
PHPUnitの多重起動でお困りの方は、まず適当なテストメソッド1つでCIを動かしてみると良いかもしれません。
(テストメソッド1つだと多重起動はせずエラーがちゃんと出てくれます。)

参考文献