æ®éãããªãã¢ããã³ã°ãã¬ã¼ã ã¯ã¼ã¯AspectMockããã¯ãã«éãã
ãã®è¨äºã¯PHP Advent Calendar 2014ã®10æ¥ç®ã§ããæ¨æ¥ã¯wateradaããã®ãPHPã³ã¼ãã®ã¬ãã¥ã¼çµæãå ±æãã¦ã¿ããã§ããã
ä»æ¥ã¯ãã¤ã±ã¦ãã¢ããã³ã°ãã¬ã¼ã ã¯ã¼ã¯AspectMockãç´¹ä»ãã¾ãã
ãã¹ãã«é¢ãããããã誤解
以ä¸ã®ãããªã¯ã©ã¹ãããå ´åãModel_FormãActive Recordã ã¨ãã¦ãããã®ã¯ã©ã¹ã¯ããã¼ã¿ããã¼ã¹ãæä½ãããã«ã¦ããããã¹ããããã¨ããã¦ããã¾ãããã¨è¨ã人ããã¾ãã
class Controller_Admin_Form extends Controller_Admin
{
public function action_index()
{
$data['forms'] = Model_Form::find(
'all',
array('order_by' => array('created_at' => 'desc'))
);
$this->template->title = "åãåãã";
$this->template->content = View::forge('admin/form/index', $data);
}
}
Model_Form::find()ã¡ã½ããããã¼ãã³ã¼ãããã¦ããããã§ãã
ããããModel_Form::find()ããã¹ãããã«ï¼ã¢ãã¯ï¼ã§ç½®ãæãããã¨ãã§ããã°ããã¼ã¿ãã¼ã¹ãªãã§ãã¹ããããã¨ã¯ãã¡ããå¯è½ã§ãã
ãããAspectMockãªãç°¡åã«ã§ãã¾ãã
test::double('Model_Form', ['find', []]);
ããã§ãModel_Form::find()ã¯ç©ºã®é åãè¿ãããã«ãªãã¾ãã
ãã¼ã¿ãã¼ã¹ãæä½ããã«ãã¹ãå¯è½ã«ãªãã¾ãããã¤ã¾ããéçã¡ã½ããããã¹ãã§ããªãã¨ããã®ã¯AspectMockããªãã£ãæ代ã®å¤ãç¥èã§ããç¾å¨ã¯ãæ£ããããã¾ããã
Note: éçã¡ã½ããããã¼ãã³ã¼ãããã³ã¼ãã£ã³ã°ãæ¨å¥¨ãã¦ããããã§ã¯ããã¾ããããã¹ãã§ããªãã¨ãã説ã¯åã«æ£ãããªãã¨è¨ã£ã¦ããã ãã§ãã
Note: AspectMock以åã§ãrunkitãªã©ã®PHPã®æ©è½æ¡å¼µã使ãã°åããããªãã¨ã¯å®ç¾ã§ãã¾ããã
AspectMockã¨ã¯ï¼
AspectMockã¯æ®éãããªãPHPã®ã¢ããã³ã°ãã¬ã¼ã ã¯ã¼ã¯ãã¢ã¹ãã¯ãæåããã°ã©ãã³ã°ã¨ã¤ã±ã¦ãGo-AOPã©ã¤ãã©ãªã®ãã¯ã¼ã§ãAspectMockã¯ã»ã¨ãã©å ¨ã¦ã®PHPã³ã¼ãã®ã¹ã¿ãã¨ã¢ãã¯ãä½æã§ããï¼ https://github.com/Codeception/AspectMock
AspectMockã«ã¯ä»¥ä¸ã®ãããªç¹å¾´ãããã¾ãã
- éçã¡ã½ããã®ãã¹ãããã«ã®ä½æãå¯è½
- ã¡ã½ããã®åçãªå¤æ´ãå¯è½
- åå空éå ã®é¢æ°ã®ãã¹ãããã«ã®ä½æãå¯è½
- è¦ããããã·ã³ãã«ãªã·ã³ã¿ãã¯ã¹
AspectMockã®è¦ä»¶
PHP 5.4以ä¸ãå¿ è¦ã§ãã
AspectMockã®ã¤ã³ã¹ãã¼ã«ã¨è¨å®
AspectMockã¯ãComposerããç°¡åã«ã¤ã³ã¹ãã¼ã«ã§ãã¾ãã
$ composer require codeception/aspect-mock:* --dev
注æ
- éãã®ã§æ¬çªç°å¢ã«ã¯ã¤ã³ã¹ãã¼ã«ããªãæ¹ããã
- å¿ ãPHPUnitãããã¸ã§ã¯ãå ã«ã¤ã³ã¹ãã¼ã«ãã
ã¤ã³ã¹ãã¼ã«ãå®äºãããããã¹ãå®è¡æã«AspectMockã使ãããã«è¨å®ãã¾ããComposerã®ãªã¼ããã¼ãã使ã£ã¦ããå ´åã¯ä»¥ä¸ã®ããã«è¨å®ãã¾ãã
require __DIR__.'/../vendor/autoload.php'; // Composerã®ãªã¼ããã¼ã
$kernel = \AspectMock\Kernel::getInstance();
$kernel->init([
'debug' => true,
'includePaths' => [__DIR__.'/../src'],
'cacheDir' => __DIR__.'/cache/AspectMock',
]);
$kernel->init()ã®å¼æ°
é ç® | 説æ |
---|---|
appDir | Webã¢ããªã®ã«ã¼ããã©ã«ããããã©ã«ãã¯Composerã®vendorãã©ã«ãã®ãããã©ã«ã |
includePaths | AOPãé©ç¨ãã¦ç½®ãæ¿ããããã©ã«ã |
excludePaths | AOPãé©ç¨ããªããã©ã«ãããã¹ããã©ã«ãã¯æå®ãã¹ã |
cacheDir | ãã£ãã·ã¥ãã©ã«ã |
PHPUnitã®è¨å®
ç¶ãã¦ãPHPUnitããAspectMockã使ãããã®è¨å®ããã¾ããã¾ããbackupGlobals
ãå¿
ãfalse
ã«ãã¾ãã
phpunit.xml
<phpunit bootstrap="bootstrap.php" backupGlobals="false">
ããã¦ãtearDown()ã¡ã½ããã§ç»é²ãããã¹ãããã«ãåé¤ããããã«ãã¾ãã
TestCase
<?php
use AspectMock\Test as test;
abstract class TestCase extends \PHPUnit_Framework_TestCase
{
protected function tearDown()
{
test::clean(); // ç»é²ãããã¹ãããã«ãåé¤
}
}
AspectMockã®ä½¿ãæ¹
ããã§ã¯ãAspectMockã®ä½¿ãæ¹ãè¦ã¦ããã¾ãããã
éçã¡ã½ããã®ç½®ãæã
éçã¡ã½ãããç½®ãæããæ§æã¯ä»¥ä¸ã®ãããªã·ã³ãã«ãªãã®ã§ãã
æ§æ
test::double('ã¯ã©ã¹å', ['ã¡ã½ããå' => è¿ãå¤]);
@return ClassProxy
ãããªãè¦ãããã¾ããããã®å ´åãClassProxyã¯ã©ã¹ã®ãªãã¸ã§ã¯ããè¿ãã¾ãã
æå®ã¯ã©ã¹ã®æå®ã¡ã½ãããç½®ãæãã
$fs = test::double('Fuel\Core\Fieldset', ['repopulate' => true]);
ããã§Fuel\Core\Fieldsetã¯ã©ã¹ã®repopulate()ã¡ã½ããã¯trueãè¿ãããã«ãªãã¾ãã
ä¾å¤ãçºçããã
$model_mail = test::double(
'Model_Mail',
['send' => function() { throw new EmailSendingFailedException; }]
);
ããã§Model_Mailã¯ã©ã¹ã®send()ã¡ã½ããã¯ä¾å¤EmailSendingFailedExceptionãæããããã«ãªãã¾ãã
å¼æ°ã®å¤ã«ãããã¹ãããã«ãè¿ãå¤ãå¤æ´ãã
å¼æ°ã®å¤ã«ãããã¹ãããã«ã®åä½ãå¤æ´ãããã¨ãå¯è½ã§ãã
test::double('Fuel\Core\Config', ['get' => function ($arg) {
if ($arg === 'foo.bar') {
return 'foo.bar';
} else {
return 'baz';
}
}]);
å¼æ°ã®å¤ãfoo.bar
ã®å ´åã¯ãfoo.bar
ãè¿ãããã®ä»ã®å ´åã¯baz
ãè¿ãã¾ãã
å¼æ°ã®å¤ã«ããå®éã®ã¡ã½ãããå®è¡ãã
å¼æ°ã®å¤ã«ããå®éã®ã¡ã½ãããå®è¡ãããã¨ãå¯è½ã§ãã
test::double('Fuel\Core\Config', ['get' => function ($arg) {
if ($arg === 'foo.bar') {
return 'foo.bar';
} else {
// ã¢ãã¯ããã«å®éã®ã¡ã½ãããå®è¡ããã
return __AM_CONTINUE__;
}
}]);
é¢æ°ã®ç½®ãæã
åå空éå ã«ããé¢æ°ã¯åãããã«ç½®ãæãã§ãã¾ãã
æ§æ
test::func('åå空é', 'é¢æ°å', è¿ãå¤);
@return FuncProxy
PHPå é¨é¢æ°ã®ç½®ãæã
$func = test::func(__NAMESPACE__, 'header', '');
ç¾å¨ã®åå空éå ã§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); // å¼ã³åºãåæ°ã®æå®
ãããã®ã¡ã½ããã¯ãProxyã¯ã©ã¹ï¼ClassProxyããã³InstanceProxyï¼ãæã¤ã¡ã½ããã«ãªãã¾ãã
ã¢ãã¯ãªãã¸ã§ã¯ããåå¾ããã«ã¯ï¼
ã¿ã¤ããã³ãã§æå®ã®ã¿ã¤ãã®ã¢ãã¯ãå¿ è¦ãªå ´åã¯ãProxyã¯ã©ã¹ããã¢ãã¯ãªãã¸ã§ã¯ããåå¾ãã¾ãã
ClassProxyã®å ´å
// ã³ã³ã¹ãã©ã¯ã¿ãå¼ã°ãã«ã¢ãã¯ãªãã¸ã§ã¯ããåå¾
$user = test::double('User')->make();
// ã³ã³ã¹ãã©ã¯ã¿ãå¼ã³åºãã¢ãã¯ãªãã¸ã§ã¯ããåå¾
$user = test::double('User')->construct([
'name' => 'davert',
'email' => '[email protected]'
]);
InstanceProxyã®å ´å
$user = test::double(new User)->getObject();
AspectMockã®ä»çµã¿
ãã¦ãã©ããã¦AspectMockã§ã¯ãã®ãããªãã¨ãå¯è½ãªã®ã§ãããï¼
AspectMockã¯ã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;
}
}
ãã®ããã«ãã¦ãæå®ã®ã¡ã½ããããã¹ãããã«ã§ç½®ãæãããã©ããã¨ããå¦çããã¦ããããã§ãã
ããã«ç¥ãã«ã¯ï¼
ããã«ç¥ãããå ´åã¯ãAspectMockã®ãªãã¸ããªã解説è¨äºãªã©ãã覧é¡ãã¾ããå ¬å¼ã®ããã¥ã¡ã³ãï¼è±èªï¼ã¯ãªãã¸ããªã«ããã¾ãã
- https://github.com/Codeception/AspectMock
- Understanding AspectMockï¼è±èªï¼
- Nothing is Untestable: AspectMock in Actionï¼è±èªï¼
- ã¬ã¬ã·ã¼ã³ã¼ãã¨AspectMock
- ãã¯ããã¦ã®ãã¬ã¼ã ã¯ã¼ã¯ã¨ãã¦ã®FuelPHP 第2ç(æ¹è¨ç)ã
ï¼2014-12-10 13:38 追è¨ï¼
AspectMockã®ã¾ã¨ã
- éçã¡ã½ãããé¢æ°ã®ãã¹ãããã«ãä½æã§ãã¾ã
- ãã¹ãããã«ä½æã®æ§æã¯ç°¡åã§è¦ãããã¾ã
- ãã¹ãã§ããªããã®ã¯ã»ã¼ããã¾ãã
- ã¬ã³ã¬ã³ãã¹ããã¾ãããâª
ãã®è¨äºã¯PHP Advent Calendar 2014ã®10æ¥ç®ã§ããææ¥ã¯ne_sachirouããã®ãPHPã§ç°¡åã«è¯éºã«DIã¨AOPããã¡ããã§ãã
Date: 2014/12/10