Symfony4でServiceEntityRepositoryを継承したRepositoryのテストをする

Symfony4でServiceEntityRepositoryを継承したRepositoryのテストをする

October 4, 2019,
tags: symfony doctrine repository test


このエントリーをはてなブックマークに追加

Symfony4でデータベースのテストをしたら、ServiceEntityRepositoryを継承したReposotiroyのテストがうまく行きませんでした。
最初書いたテストコードはこんな感じです。

// src/Repository/UserRepository.php
class UserRepository extends ServiceEntityRepository
{
  public function averageScore() :float
  {
		...
  }
}
// tests/UserRepositoryTest.php
class UserRepositoryTest extends KernelTestCase
{
	/**
  * @var UserRepository
  */
  private $repository;

  protected function setUp(): void
  {
      $kernel = self::bootKernel();
      $em = $kernel->getContainer()->get('doctrine');
      $repository = $em->getRepository(User::class);
  }

  public function testAverage(): void
  {
      $actual = $this->repository->averageScore();
      static::assertSame(4.5, $actual);
  }

}

このテストコードだと$this->repositoryに入っているオブジェクトがEntityRepositoryになってしまい、aveerageScore()メソッドが無いよとエラーになってしまいます。

解決策

DIからUserRepositoryのオブジェクトを取得する方法を使うのが今は良いかと思います。(てかそれしかなさそう)

// tests/UserRepositoryTest.php
protected function setUp(): void
{
    $kernel = self::bootKernel();
    $repository = $kernel->getContainer()->get(UserRepository::class);
}

しかし、これだとpublic = falseとなった状態なのでUserRepository::classのオブジェクトが取得できなくてエラーになります。 この問題は service_test.yamlを作成してpublic = trueに設定を解決しました。

# config/services_test.yaml

services:
    _defaults:
        autowire: true
        autoconfigure: true
    App\:
        resource: '../src/*'
        exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
        public: true

これでテストのときはpublic = trueになるのでDIからオブジェクトが取得できます。

最後に

他にももっと良い方法があると思いますが、僕はわからなかったので知っている方がいたらコメントください!

comments powered by Disqus