1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Laravelで,Illuminate\Database\Eloquent\Modelクラスのメソッドをモックする

Posted at

環境情報

$ php --version
PHP 7.4.5 (cli) (built: Apr 19 2020 07:36:30) ( NTS )
$ composer info laravel/framework
name     : laravel/framework
descrip. : The Laravel Framework.
keywords : framework, laravel
versions : * v8.10.0

Homestead: v10.12.0
OS: Ubuntu18.04 LTS

Illuminate\Database\Eloquent\Modelのテスト

Laravelの Illuminate\Database\Eloquent\Model を継承したクラスに,publicメソッドを生やすことがあります.
このテスト設計が果たして正しいのかについては模索中ですが,ひとまず呼び出し元の関数をテストしないといけないのでモックすることにしました.
しかし,これが凄まじく理解し難く,そもそも実装するにたどり着くまでが非常に難しかったので,ここに共有しようと思います.

とりあえず動かす

cloneして動かせるサンプルを用意しました.これを動作させると,とりあえずモックのコードが試せます.

$ vendor/bin/phpunit tests/Unit/ExampleTest.php 
PHPUnit 9.4.1 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)
---- $mock の中身を出力 ----
/home/vagrant/blog/laravel-models-mocking-example/tests/Unit/ExampleTest.php:29:
class App\Models\ExampleModel#419 (20) {
  protected $_mockery_expectations =>
  ...(略)...
}
-------------------------------

Time: 00:00.096, Memory: 20.00 MB

OK (1 test, 2 assertions)

何を変更したのか

このコミットでの変更内容が全てです.
https://github.com/tarohida/laravel-models-mocking-example/commit/e351eb15ae5187b0c7d895cf87e10d2a0fc6e307

構成ファイル

App\Models\ExampleModel

今回モックする対象のモデルクラスです.artisanコマンドで生成してから変更を加えていません.

app/Models/ExampleModel.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class ExampleModel extends Model
{
    use HasFactory;
}

App\Models\ExampleModelUse

モック対象のExampleModelクラスを呼び出すクラスです.今回のテスト対象となるクラスです.
artisanコマンドで生成した後,static関数をひとつ定義しています.

本当は,このクラスはModelクラスにする必要はないですし,Modelクラスでない方が一般的なケースかなと思うのですが,実際に laravel new から変更内容を再現する利用者1のことを考え,artisanコマンドで簡単に作成できるModelクラスとしました

app/Models/ExampleModelUse.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class ExampleModelUse extends Model
{
    use HasFactory;

    public static function method_to_be_tested()
    {
	    return ExampleModel::method_do_not_exists();
    }
}

Tests\Unit\ExampleTest

テストケースです.laravelがデフォルトで作成するExampleTestクラスを書き換えています.
上記コミットの変更差分を確認いただければ,Mockに必要な箇所がよりわかりやすいかと思います.

tests/Unit/ExampleTest.php
<?php

namespace Tests\Unit;

use Tests\TestCase;
use Mockery;
use App\Models\ExampleModelUse;

class ExampleTest extends TestCase
{
    public function setUp(): void
    {
        parent::setUp();
    }

    /**
     * A basic test example.
     *
     * @return void
     */
    public function testBasicTest()
    {
    // ExampleModelのmethod_do_not_exists()メソッドをモックする
    $mock = Mockery::mock('overload:App\Models\ExampleModel');
    $mock->shouldReceive('method_do_not_exists')
        ->once()->andReturn('mocked_value');

    echo "---- \$mock の中身を出力 ----\n";
    var_dump($mock);
    echo "-------------------------------";

    // テスト対象のメソッドを呼び出して,assertする
    $example_ret_value = ExampleModelUse::method_to_be_tested();
    $this->assertSame('mocked_value', $example_ret_value);
    }
}

参考元記事

この記事が全てです.リポジトリ
この記事の内容を手元のコードに取り込んで,無事モックが動作しました.

動いたコードを新しいプロジェクトに切り出して作成したのが,今回のGitリポジトリです.

  1. 果たして現れるのか???

1
2
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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?