初めに
FlowにはFunctionalTestという機能があり、PHPUnitを用いてAPIやDBなどの機能をテストすることができます。今回はこのFunctionalTestを試してみます。
実行方法
今回はControllerを対象にテストを行います。
テスト対象は以下です。単純にレスポンスを返すだけのシンプルなAPI。
<?php
namespace Neos\Welcome\Controller;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Mvc\Controller\ActionController;
class FunctionalTestController extends ActionController
{
/**
* @Flow\Inject
* @var \Neos\Flow\Mvc\View\JsonView
*/
protected $view;
/**
* @return void
*/
public function indexAction()
{
$this->view->assign('value', array('testResponse'));
}
}
1. テストクラスを作成
以下のようなテストクラスを作成しました。
FunctionalTestをするには、FlowのNeos\Flow\Tests\FunctionalTestCase
というクラスを継承する必要があります。
<?php
namespace Neos\Welcome\Tests\Functional\Controller;
use Neos\Flow\Tests\FunctionalTestCase;
use Psr\Http\Message\ServerRequestFactoryInterface;
class FunctionalTestControllerTest extends FunctionalTestCase
{
/**
* @var bool
*/
protected $testableHttpEnabled = true; // ★APIのリクエストを送るためのフラグ
/**
* @var ServerRequestFactoryInterface
*/
protected $serverRequestFactory;
/**
* Additional setup: Routes
*/
protected function setUp(): void
{
parent::setUp();
// ★APIのルーティング設定
$this->registerRoute('test', 'Neos.Welcome/Aop/index(/{@action})', [
'@package' => 'Neos.Welcome',
'@controller' => 'FunctionalTest',
'@action' => 'index',
]);
$this->serverRequestFactory = $this->objectManager->get(ServerRequestFactoryInterface::class);
}
/**
* @test
*/
public function functionaltest()
{
// ★実行と検証
$response = $this->browser->request('http://localhost:8081/Neos.Welcome/Aop/index');
self::assertSame(200, $response->getStatusCode());
}
}
2. テスト実行
以下のコマンドでテストを実行します。
設定ファイルで定義しているBuild\BuildEssentials\PhpUnit\FunctionalTests.xml
はFlowにデフォルトで搭載されているPHPUnitの設定ファイルです。
$ .\bin\phpunit -c .\Build\BuildEssentials\PhpUnit\FunctionalTests.xml .\Packages\Application\Neos.Welcome\Tests\Functional\Controller\FunctionalTestControllerTest.php --debug
PHPUnit 9.6.22 by Sebastian Bergmann and contributors.
Test 'Neos\Welcome\Tests\Functional\Controller\FunctionalTestControllerTest::functionaltest' started
Test 'Neos\Welcome\Tests\Functional\Controller\FunctionalTestControllerTest::functionaltest' ended
Time: 00:00.093, Memory: 84.00 MB
OK (1 test, 1 assertion)
無事にテストが実行されました!
注意点
実行した際、以下のエラーが出て実行をすることができませんでした。
$ .\bin\phpunit -c .\Build\BuildEssentials\PhpUnit\FunctionalTests.xml .\Packages\Application\Neos.Welcome\Tests\Functional\Controller\FunctionalTestControllerTest.php --debug
PHPUnit 9.6.22 by Sebastian Bergmann and contributors.
Test 'Neos\Welcome\Tests\Functional\Controller\FunctionalTestControllerTest::functionaltest' started
Test 'Neos\Welcome\Tests\Functional\Controller\FunctionalTestControllerTest::functionaltest' ended
Time: 00:00.075, Memory: 82.00 MB
There was 1 error:
1) Neos\Welcome\Tests\Functional\Controller\FunctionalTestControllerTest::functionaltest
TypeError: Attribute value must be of type int for selected attribute, string given
C:\Path\To\Project\Packages\Libraries\doctrine\dbal\lib\Doctrine\DBAL\Driver\PDOConnection.php:40
C:\Path\To\Project\Packages\Libraries\doctrine\dbal\lib\Doctrine\DBAL\Driver\PDOSqlite\Driver.php:42
C:\Path\To\Project\Packages\Libraries\doctrine\dbal\lib\Doctrine\DBAL\Connection.php:412
C:\Path\To\Project\Data\Temporary\Testing\Cache\Code\Flow_Object_Classes\Neos_Flow_Persistence_Doctrine_EntityManagerFactory.php:111
C:\Path\To\Project\Packages\Framework\Neos.Flow\Classes\ObjectManagement\ObjectManager.php:517
C:\Path\To\Project\Packages\Framework\Neos.Flow\Classes\ObjectManagement\ObjectManager.php:206
C:\Path\To\Project\Data\Temporary\Testing\Cache\Code\Flow_Object_Classes\Neos_Flow_Persistence_Doctrine_PersistenceManager.php:536
C:\Path\To\Project\Packages\Framework\Neos.Flow\Classes\ObjectManagement\DependencyInjection\DependencyProxy.php:59
C:\Path\To\Project\Packages\Framework\Neos.Flow\Classes\ObjectManagement\DependencyInjection\DependencyProxy.php:59
C:\Path\To\Project\Packages\Framework\Neos.Flow\Classes\ObjectManagement\DependencyInjection\DependencyProxy.php:99
C:\Path\To\Project\Data\Temporary\Testing\Cache\Code\Flow_Object_Classes\Neos_Flow_Persistence_Doctrine_PersistenceManager.php:142
C:\Path\To\Project\Packages\Framework\Neos.Flow\Classes\ObjectManagement\DependencyInjection\DependencyProxy.php:99
C:\Path\To\Project\Data\Temporary\Testing\Cache\Code\Flow_Object_Classes\Neos_Flow_Http_Client_InternalRequestEngine.php:162
C:\Path\To\Project\Data\Temporary\Testing\Cache\Code\Flow_Object_Classes\Neos_Flow_Http_Client_Browser.php:219
C:\Path\To\Project\Data\Temporary\Testing\Cache\Code\Flow_Object_Classes\Neos_Flow_Http_Client_Browser.php:172
C:\Path\To\Project\DistributionPackages\Neos.Welcome\Tests\Functional\Controller\FunctionalTestControllerTest.php:41
C:\Path\To\Project\bin\phpunit:122
ERRORS!
Tests: 1, Assertions: 0, Errors: 1.
FunctionalTestはデフォルトでSQLiteを用いる設定になっているのですが、そのままだとDoctrineのPDOConnectionで渡す引数の型が違うというエラーがでてしまいました。
理由はわからないのですが、原因の箇所のコードを以下のように修正すると通るようになりました。
今回は試すだけなのでこれでいいですが、理由は調べようと思います。
public function __construct($dsn, $user = null, $password = null, ?array $options = null)
{
try {
- parent::__construct($dsn, (string) $user, (string) $password, (array) $options);
+ parent::__construct($dsn, (string) $user, (string) $password);
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, [Statement::class, []]);
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $exception) {
throw Exception::new($exception);
}
}
終わりに
今回FlowのFunctionalTestを使用してAPIのテストを実施しました。今回は単純なAPIでしたが、DBまでの一気通貫のテストもできそうなので、別の記事で試してみようと思います。
ここまでご覧いただきありがとうございました!