aspectmock 最強のモッキングフレームワーク
DESCRIPTION
Nagoya.php vol.7 LT資料TRANSCRIPT
AspectMock最強のモッキングフレームワーク
2014/11/16 Nagoya.php vol.7kenjis
AspectMockとは?AspectMockは普通じゃないPHPのモッキングフレームワーク。
アスペクト指向プログラミングとイケてるGo-AOPライブラリのパワーで、
AspectMockはほとんど全てのPHPコードのスタブとモックを作成できる!
https://github.com/Codeception/AspectMock
特徴静的メソッドのテストダブルの作成メソッドの動的な変更名前空間内の関数のテストダブルの作成覚えられるシンプルなシンタックス
つまりNothing is Untestable!Easy to Use
要件PHP 5.4+
インストール方法$ composer require codeception/aspect-mock:* --dev
注意
重いので本番環境にはインストールしない方がよい必ずPHPUnitもプロジェクト内にインストールする
設定例require __DIR__.'/../vendor/autoload.php'; // Composerのオートローダ
$kernel = \AspectMock\Kernel::getInstance();$kernel->init([ 'debug' => true, 'includePaths' => [__DIR__.'/../src'], 'cacheDir' => __DIR__.'/cache/AspectMock',]);
Composerのオートローダを使っている場合
$kernel->init()の引数項目 説明
appDir Webアプリのルートフォルダ。デフォルトはComposerのvendorフォルダのあるフォルダ
includePaths AOPを適用して置き替えたいフォルダexcludePaths AOPを適用しないフォルダ。テストフォルダ
は指定すべき
cacheDir キャッシュフォルダ
PHPUnitの設定phpunit.xml
<phpunit bootstrap="bootstrap.php" backupGlobals="false">
TestCase<?phpuse AspectMock\Test as test;
abstract class TestCase extends \PHPUnit_Framework_TestCase{ protected function tearDown() { test::clean(); // 登録したテストダブルを削除 }}
静的メソッドの置き換え構文
test::double('クラス名', ['メソッド名' => 返り値]);
@return ClassProxy
例
$fs = test::double('Fuel\Core\Fieldset', ['repopulate' => true]);
$model_mail = test::double( 'Model_Mail', ['send' => function() { throw new EmailSendingFailedException; }]);
静的メソッドの置き換え例:引数の値によりモックが返す値を変更する
test::double('Fuel\Core\Config', ['get' => function ($arg) { if ($arg === 'foo.bar') { return 'foo.bar'; } else { return 'baz'; }}]);
例:引数の値により実際のメソッドを実行する
test::double('Fuel\Core\Config', ['get' => function ($arg) { if ($arg === 'foo.bar') { return 'foo.bar'; } else { // モックせずに実際のメソッドを実行させる return __AM_CONTINUE__; }}]);
関数の置き換え構文
test::func('名前空間', '関数名', 返り値);
@return FuncProxy
例
$func = test::func(__NAMESPACE__, 'header', '');
メソッド呼び出しの検証例
$user = test::double(new User, ['getName' => 'davert']);$this->assertEquals('davert', $user->getName());
$user->verifyMethodInvoked('getName'); // 呼び出されたか?$user->verifyMethodInvoked('setName', ['davert']); // 引数の指定$user->verifyMethodInvokedOnce('getName'); // 一度だけ?$user->verifyMethodNeverInvoked('setName'); // 呼び出されない?$user->verifyMethodInvokedMultipleTimes('setName', 1); // 呼び出し回数の指定
モックオブジェクトの取得ClassProxy
// コンストラクタを呼ばずにモックオブジェクトを取得$user = test::double('User')->make();
// コンストラクタを呼び出しモックオブジェクトを取得$user = test::double('User')->construct([ 'name' => 'davert', 'email' => '[email protected]']);
InstanceProxy$user = test::double(new User)->getObject();
仕組みAOPによりモックするメソッドをインターセプトして置き換える
仕組みGo AOPを使いPHPファイルを動的に書き換え
class User{ function setName($name) { $this->name = $name; } }
↓
class User{ function setName($name) { if (($__am_res = __amock_before($this, __CLASS__, __FUNCTION__, array(), false)) !== __AM_CONTINUE__) return $__am_res; $this->name = $name; }
}
さらに知るには
『 』
https://github.com/Codeception/AspectMockUnderstanding AspectMockNothing is Untestable: AspectMock in ActionレガシーコードとAspectMockはじめてのフレームワークとしてのFuelPHP 改訂版
AspectMockのまとめ静的メソッドや関数のモックを作成できますモック作成の構文は簡単で覚えられますテストできないものはほぼありませんガンガンテストしましょう♪