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からオブジェクトが取得できます。
最後に
他にももっと良い方法があると思いますが、僕はわからなかったので知っている方がいたらコメントください!