0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【PHPフレームワークFlow】FunctionalテストでDBアクセスを含めたテストを実行する

Posted at

初めに

前回はこちらの記事でFunctionalテストについて紹介しました。今回はDBアクセスのあるAPIをFunctionalテストで実装していこうと思います。

functionalテストとは

Functionalテストとは機能単位のテストを行うための機能です。Laravelのfeatureテストのようなイメージだと思います。

詳しくは前回の記事をご参照ください。

DBアクセスを含めたFunctionalテストを書いてみる

前回の記事では固定値を返すだけの単純なAPIに対してFunctionalテストを作成しました。今回はDBアクセスを含めたControllerに対するFunctionalテストを作成してみようと思います。

こちらがテスト対象のクラスです。

テスト対象のクラス
<?php
namespace Neos\Welcome\Controller;

use Neos\Flow\Annotations as Flow;
use Neos\Flow\Mvc\Controller\ActionController;
use Neos\Welcome\Domain\Model\Functional;

class FunctionalTestController extends ActionController
{
    /**
     * @Flow\Inject
     * @var \Neos\Flow\Mvc\View\JsonView
     */
    protected $view;

    /**
     * @Flow\Inject
     * @var \Neos\Welcome\Domain\Repository\FunctionalRepository
     */
    protected $functionalRepository;

    /**
     * @return void
     */
    public function indexAction()
    {
        // DBからデータを取得
        $result = $this->functionalRepository->findAll();

        // 最初の1件をレスポンスに詰める
        $first = $result->getFirst();
        $this->view->assign('value', [
            'id' => $first->getId(),
            'functionName' => $first->getFunctionalName()
        ]);
    }
}

1. テストケース作成

以下のようなテストケースを作成しました。
ポイントは後述します。

テストクラス
<?php
namespace Neos\Welcome\Tests\Functional\Controller;

use Neos\Flow\Tests\FunctionalTestCase;
use Neos\Welcome\Domain\Model\Functional;
use Psr\Http\Message\ServerRequestFactoryInterface;
use Neos\Welcome\Domain\Repository\FunctionalRepository;

class FunctionalTestControllerTest extends FunctionalTestCase
{

    /**
     * @var bool
     */
    protected $testableHttpEnabled = true;

    /**
     * ★ポイント1
     * @var boolean
     */
    protected static $testablePersistenceEnabled = true;

    /**
     * @var \Neos\Welcome\Domain\Repository\FunctionalRepository
     */
    protected $functionalRepository;

    /**
     * ★ポイント2
     * Additional setup
     */
    protected function setUp(): void
    {
        parent::setUp();
        $this->functionalRepository = $this->objectManager->get(FunctionalRepository::class);
    }

    /**
     * @test
     */
    public function functionaltest()
    {
        // Arrange
        // ★ポイント3
        $testData = new Functional("testId", "testName");
        $this->functionalRepository->add($testData);
        $this->persistenceManager->persistAll();

        // Act
        $response = $this->browser->request('http://localhost:8081/Neos.Welcome/FunctionalTest/index');
        $responseArray = json_decode($response->getBody()->getContents(), true);

        // Assert
        self::assertSame('testId', $responseArray['id']);
        self::assertSame('testName', $responseArray['functionName']);
        self::assertSame(200, $response->getStatusCode());
    }
}

ポイント

  • DB接続を行うテストでは$testablePersistenceEnabledtrueにする
    /**
     * @var boolean
     */
    protected static $testablePersistenceEnabled = true;
  • データ作成や検証で利用するRepositoryはsetup()の中で値を入れる
    /**
     * @var \Neos\Welcome\Domain\Repository\FunctionalRepository
     */
    protected $functionalRepository;

    protected function setUp(): void
    {
        parent::setUp();
        $this->functionalRepository = $this->objectManager->get(FunctionalRepository::class);
    }
  • テストケースの中でDBのデータを作成
    • persistAll()を行うことで永続化できる
        // Arrange
        $testData = new Functional("testId", "testName");
        $this->functionalRepository->add($testData);
        $this->persistenceManager->persistAll();

2. Settings.yamlにDB接続設定を記載

設定ファイルにDB接続設定を記載します。テストはTestingコンテキストで実行されるため、ConfigtrationのTesting配下にSettings.yamlを作成し、そこに記載します。

Quickstart
    ├ Configuration/
        ├ Testing
        |    └ Settings.yaml(★)
        └ Settings.yaml

MySQLを使用してテストを行いたかったので、以下のように記載しました。
dbnameをmy_database_for_testとしていますが、このDBをあらかじめ作成しておく必要があります。
マイグレーションはFunctionalTest内で実行してくれるため必要ありません。create database hogeのみでOK。

Neos:
  Flow:
    persistence:
      backendOptions:
        driver: 'pdo_mysql'
        charset: 'utf8mb4'
        host: '127.0.0.1'    # Docker service name
        dbname: 'my_database_for_test'  # Database name
        user: 'root'  # MySQL user
        password: 'root'  # MySQL password
        port: '3306'  # MySQL port
        driverOptions:
          1002: 'SET SESSION wait_timeout=5'

3. テスト実行

実行結果がこちらです。
テスト一つに対して4秒かかっているのは、マイグレーションやデータ作成/削除のせいですかね、複数テストがあった時にどうなるのかはまた今度検証しようと思います。

$ .\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:04.864, Memory: 92.00 MB

OK (1 test, 3 assertions)

終わりに

前回に引き続き、今回はFlowのFunctionalテストを試してみました。
DB接続のテストがサクッとつくれるのは開発が捗りますね。今回はControllerから実行していますが、FlowのFW自体のFunctionalテストでは、Repository自体にDBアクセスを含めたFunctionalテストを作成しており、UnitTestのような感覚で書けるのはいいなとおもいましたね。可能性を感じています。

ここまでご覧いただきありがとうございました!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?