2016-03-21 11 views
0

私のPHPUnitテストの実行速度が遅いことに気がつきました.GroupUsersというテストケースごとに8秒ほどです。私はデバッグを開始し、私の模擬された静的クラスがまだ実行されていることと、GroupUserの作成時にスローされるイベントのリスナーに時間の大半が消費されていることがわかりました。このイベントは、データベースからユーザーのリストを取得し、私が嘲笑している静的なBrioMailerクラスを使用して適切な電子メールを送信します。モックで静的メソッドをモックする

私は電子メールの送信にのみ使用される静的クラスを持っています。このクラスには、テンプレートとメールオプションを変更するいくつかのメソッドがあり、self::sendEmailを呼び出して実際にメールを送信します。

私はLaravel 5を使用しています。実際にメールを送信しないようにしていますので、私はふりをするモードをオンにしました。しかし、クラスを嘲笑しても呼び出されたメソッドはまだ実行されていますが、私はmailerメソッドにデバッグコードを入力し、ユニットテストを実行することでこれを確認しました。

私のテストケース

public function testNotificationSentToMemberWhenNewGroupMediaIsSaved() 
{ 
    $brioMailer = \Mockery::mock('alias:BrioMailer'); 

    $data = self::getRandomCommunityWithAssociatedData(); 

    $community = $data['community']; 
    $admin = $data['admins'][0]; 

    $firstUser = $data['users'][0]; 
    $firstUser->created_by = $admin->id; 
    $secondUser = $data['users'][1]; 
    $secondUser->created_by = $admin->id; 

    $notifications = $secondUser->notificationPreferences; 
    $notifications->{'new-media-member'} = 1; 
    $secondUser->notificationPreferences()->save($notifications); 

    $asset = factory(Asset\Video::class)->make(); 
    $asset->community()->associate($community); 
    $asset->user()->associate($admin); 
    $asset->save(); 

    $group = factory(Group::class)->make(); 
    $group->community()->associate($community); 
    $group->created_by = $admin->id; 
    $group->save(); 

    foreach([$firstUser, $secondUser, $admin] as $user) { 
     $groupUser = factory(GroupUser::class)->make(); 
     $groupUser->user_id = $user->id; 
     $groupUser->group_id = $group->id; 
     $groupUser->created_by = $admin->id; 
     $groupUser->save(); 
    } 

    $groupMedia = factory(GroupMedia::class)->make(); 
    $groupMedia->asset()->associate($asset); 
    $groupMedia->user()->associate($firstUser); 
    $groupMedia->group()->associate($group); 
    $groupMedia->published_date = date('Y-m-d H:i:s', strtotime('-1 day')); 

    $this->assertTrue($groupMedia->save()); 

    $brioMailer->shouldReceive('newMediaItemMember')->with($secondUser, $firstUser, $groupMedia); 
} 

私は、問題はイベントリスナーがメールを送信する「ふり」するために、ユーザーごとに8秒まで取っているということであることを確認しました。私はオブジェクトを嘲笑していますが、静的メソッドを実行するように見えます。

私は最初にLaravelのIoCコンテナに追加する必要があると考えていましたが、これはアプリケーションのさまざまな部分から呼び出され、もともとIoCに保存されていないオートロードされた静的クラスです。

注意すべき点は、テストケースの下部に向かう線が適切に機能しているように見えることです。 shouldReceive() - > with()の引数の順序を変更すると、エラーがスローされます。

私は静的メソッド呼び出しがモックオブジェクトに当たっていない理由と、なぜそれが電子メールをまったく送信しようとしているのかについて紛失しています。

今後の読者への援助や指示があれば幸いです。

+1

あなたはそれが好きではありませんが、適切な解決策は、あなたの設計を固定し、静的な呼び出しから電子メールを送信しないことです。必要なときはいつでも、電子メールの送信を担当する適切なオブジェクトを注入して、テストで偽装してください。サイドノート:あなたのテストは全く読めません。フィクスチャ作成を抽出することを検討してください(少なくともメソッドに対してですが、テストデータビルダーとマザーオブジェクトについては読んでください)。 –

+0

メールを送信するためにリスナーと一緒にサービスプロバイダまたはイベントを使用する必要がある場合は、今朝決定します。静的クラスを見つけることは、テストするのが非常に面倒です。また、Model FactoryとFakerを使用して模擬テストデータが作成されていますが、テスト用にリレーションシップを設定する必要があります。確かに私はこれを別のメソッドに抽出することができましたが、そのメソッドはすべての関連したオブジェクトの配列を返さなければならず、それぞれのテストは異なります。 –

答えて

-2

静的メソッドの代わりにファサードを使用します。

最近、ファサードを模擬するのは簡単です。彼らはそれのためのドキュメントを持っています。

https://laravel.com/docs/5.3/mocking#mocking-facades

あなたがファサードを好きではない場合は、[OK]をクリックします。シングルトンを試してみてください。

+0

なぜ2つのマイナスがありますか? –

関連する問題