テスト用の自動モック依存関係注入
injected Traitと、テスト目的ですべての依存関係をモックアウトしたクラスを簡単に作成できます。
次のパターンは非常に一般的です。
Aを作成します。Aの各依存関係を模擬するテストを作成し、それらが期待どおりに呼び出されることを主張します。テスト ロジックの多くは、最終的にはオブジェクトを構築するための定型的なものになります。 injected Traitこのボイラープレートを完全に削除し、重要なこと、つまりテスト自体に集中できるようにすることを目的としています。
最新リリースを取得するには、 composerを使用します (おそらく、開発にのみ必要になります)。
$ composer require sellerlabs/ injected --dev
Web アプリを開発していて、ユーザーがサインアップしたときにユーザーにメールを送信したいとします。簡単な例として、ユーザーが完全に電子メール アドレスによって定義されていると仮定しましょう。彼らがサインアップしたら、当然のことながら、お礼のメールを送りたいと考えます。さらに、電子メールを実際に送信せずに、実際に送信されるかどうかをテストしたいと考えています。
まず、電子メール サービスを定義しましょう。
class EmailService
{
public function email ( $ address , $ content )
{
// Send an email to $address with body $content
}
} (実際のアプリケーションでは、 email電子メールを送信します。ただし、ここでは実装には関心がありません。)
非常に単純なサインアップ プロセスを処理するUserControllerも定義しましょう。
class UserController
{
private $ service ;
public function __construct ( EmailService $ service )
{
$ this -> service = $ service ;
}
public function signUp ( $ emailAddress )
{
$ this -> service -> email ( $ emailAddress , ' Thanks for signing up! ' );
return $ emailAddress ;
}
}ここでは、コンストラクターを通じてEmailService依存関係を提供し、(信じられないほど単純な) サインアップ プロセス中にそれを使用します。
このクラスをテストするには、次の 2 つのうちの 1 つを行う必要があります。
Mockeryなどを使用してEmailServiceオブジェクトをモックし、期待される引数でemailが呼び出されることを確認します。 injected Traitすると、オプション 2 を簡単に達成できます。見てみましょう。
use SellerLabs injected injected Trait ;
/**
* Class injected Example
*
* // 1. These are helpful annotations for IDEs and language tools
* @property MockInterface $service
* @method UserController make()
*
* @author Benjamin Kovach <[email protected]>
*/
class injected Example extends PHPUnit_Framework_TestCase
{
// 2. Use our trait
use injected Trait;
// 3. Provide the name of the class to test
protected $ className = UserController::class;
public function testSignUp ()
{
// 4. Make a controller with mocked dependencies
$ controller = $ this -> make ();
$ address = ' [email protected] ' ;
// 5. We can access any mocked dependency of the class as a property
$ this -> service -> shouldReceive ( ' email ' )
-> withArgs (
[
$ address ,
' Thanks for signing up! '
]
);
$ result = $ controller -> signUp ( $ address );
$ this -> assertEquals ( $ address , $ result );
}
} injected Traitを使用するすべてのクラスには、テスト対象のクラスを見つけるために使用される$classNameプロパティが必要です。 injected Trait 、この型のオブジェクトを構築する単一のパブリック メソッドmakeを提供しますが、その依存関係を模擬し、それらをプロパティとしてテスト クラス自体に保存します。
そのため、 testSignUpでは、 make()使用してコントローラーを構築しています。これにより、 $serviceというモック化されたEmailServiceタイプのオブジェクトにアクセスできるようになります。これは、 UserControllerのコンストラクターでそのように定義されているためです。
public function __construct ( EmailService $ service )
{
$ this -> service = $ service ;
}テスト ケースの間、 $serviceメンバー変数はこのモック化されたEmailServiceにバインドされます。これにより、コントローラーのsignUpメソッドが呼び出されたときに何が起こるかを予測できます。モック化されたオブジェクトを作成するにはMockery使用します。クラス コメントにはいくつかの注釈があり、モック プロパティが動的に宣言されるため、これらのクラスの IDE オートコンプリートに役立ちます。
この例はtests/ injected Example.phpにあります。気軽に覗いてみてください!
この特性の影響は比較的小さいように思えるかもしれませんが、クラスにいくつかの依存関係がある大規模なアプリケーションで作業する場合、これによりテストがはるかに簡単になります。