Featured image of post Symfony4でServiceEntityRepositoryを継承したRepositoryのテストをする

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

Twitter ツイート Hatena Bookmark ブックマーク

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

1
2
3
4
5
6
7
8
// src/Repository/UserRepository.php
class UserRepository extends ServiceEntityRepository
{
  public function averageScore() :float
  {
		...
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 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のオブジェクトを取得する方法を使うのが今は良いかと思います。(てかそれしかなさそう)

1
2
3
4
5
6
// 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に設定を解決しました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 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
Built with Hugo
テーマ StackJimmy によって設計されています。