Symfony 1.4で実装したAPIのFunctionalテストをする際に、ファイルをPOSTする方法に迷ったので調べました。
ファイルのアップロードテストは、通常のWebサイトであれば、
$browser-> get('/upload')-> click('Upload', array('form' => array( 'file1' => sfConfig::get('sf_test_dir').'/datas/test01.jpg', ))) ;
みたいに書くのですが、テストしたいアプリケーションはAPIなので、GETするページはありません。
sfBrowserBase::clickを参考にして、こんな感じで実装しました。
まずはテスト本体。test/functional/api/hogeActionsTest.php
<?php include(dirname(__FILE__).'/../../bootstrap/functional.php'); $browser = new MyTestFunctional(new myBrowser()); $browser->loadData(); $browser-> info('JPEGファイルをアップロードできる')-> setUploadFile('file1', sfConfig::get('sf_test_dir').'/datas/test01.jpg')-> post('/upload', array('title' => 'hoge'))-> with('response')->begin()-> isStatusCode(200)-> end()-> ;
次にmyBrowserを定義します。lib/test/myBrowser.class.php
<?php class myBrowser extends sfBrowser { public function setUploadFile($key, $filename) { if (is_readable($filename)) { $fileError = UPLOAD_ERR_OK; $fileSize = filesize($filename); } else { $fileError = UPLOAD_ERR_NO_FILE; $fileSize = 0; } $this->parseArgumentAsArray($key, array( 'name' => basename($filename), 'type' => '', 'tmp_name' => $filename, 'error' => $fileError, 'size' => $fileSize, ), $this->files); } }
sfBrowserBaseクラスのfilesに対して配列でファイルの情報を書き込むと、POST直前に$_FILESに書きこんでくれます。
で、あとはMyでmyBrowser::setUploadFileを呼び出すだけです。lib/test/MyTestFunctional.class.php
<?php class MyTestFunctional extends sfTestFunctional { public function loadData() { $doctrine = Doctrine_Manager::getInstance()->getCurrentConnection()->getDbh(); $doctrine->query('SET FOREIGN_KEY_CHECKS = 0'); $doctrine->query('TRUNCATE TABLE uploads'); $doctrine->query('SET FOREIGN_KEY_CHECKS = 1'); unset($doctrine); Doctrine::loadData(sfConfig::get('sf_test_dir').'/fixtures/'); return $this; } public function setUploadFile($key, $filename) { $this->browser->setUploadFile($key, $filename); return $this; } }
こうやってsetUploadFile(…)->post(…)と呼び出せばOKです。
sfBrowserBase::callされるたびにfilesの中身はクリアされます。