Symfony Testing: using Repository pattern without connecting to database

<?php

namespace App\Controller;

use App\Repository\PostRepositoryInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class PostController extends AbstractController
{
#[Route('/post/{id}')]
public function show(int $id, PostRepositoryInterface $postRepository): Response
{
$post = $postRepository->findById($id);

return $this->render('post/show.html.twig', [
'title' => $post->getTitle(),
]);
}
}
<?php
namespace App\Repository;
use App\Entity\Post;interface PostRepositoryInterface {
public function findById(int $id):?Post;
}
<?phpnamespace App\Repository;use App\Entity\Post;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
*
@extends ServiceEntityRepository<Post>
*
* @method Post|null find($id, $lockMode = null, $lockVersion = null)
*/
class PostRepository extends ServiceEntityRepository implements PostRepositoryInterface
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Post::class);
}
public function findById(int $id): ?Post
{
return $this->find($id);
}
}
<?php

namespace App\Repository\Fake;

use App\Entity\Post;
use App\Repository\PostRepositoryInterface;

class PostRepository implements PostRepositoryInterface
{

private array $fakeData = [];

private function initData()
{
$this->fakeData = [
new Post(['id' => 1, 'title' => 'test title 1']),
new Post(['id' => 2, 'title' => 'test title 2'])
];
}

public function __construct()
{
$this->initData();
}

public function findById(int $id): ?Post
{
foreach ($this->fakeData as $model) {
if ($model->getId() == $id) {
return $model;
}
}
return null;
}
}
<?php

namespace App\Repository;

use App\Entity\Post;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\DependencyInjection\Attribute\When;

/**
*
@extends ServiceEntityRepository<Post>
*
* @method Post|null find($id, $lockMode = null, $lockVersion = null)
*/
#[When(env: 'dev')]
#[When(env: 'prod')]
class PostRepository extends ServiceEntityRepository implements PostRepositoryInterface
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Post::class);
}

public function findById(int $id): ?Post
{
return $this->find($id);
}
}
<?php

namespace App\Repository\Fake;

use App\Entity\Post;
use App\Repository\PostRepositoryInterface;
use Symfony\Component\DependencyInjection\Attribute\When;

#[When(env: 'test')]
class PostRepository implements PostRepositoryInterface
{

private array $fakeData = [];

private function initData()
{
$this->fakeData = [
new Post(['id' => 1, 'title' => 'test title 1']),
new Post(['id' => 2, 'title' => 'test title 2'])
];
}

public function __construct()
{
$this->initData();
}

public function findById(int $id): ?Post
{
foreach ($this->fakeData as $model) {
if ($model->getId() == $id) {
return $model;
}
}
return null;
}
}

Integration test aka kernel test

<?php
namespace App\Tests\Integration\Controller;

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class PostControllerTest extends KernelTestCase{

public function testShow()
{
$kernel = self::bootKernel();
$fakeRequest = Request::create('/post/1', 'GET');
$response = $kernel->handle($fakeRequest,HttpKernelInterface::MAIN_REQUEST,false);
$this->assertStringContainsString('test title 1',$response->getContent());
}

}

Application test aka WebTest

<?php
namespace App\Tests\Application\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class PostControllerTest extends WebTestCase {

public function testShow()
{
$client = static::createClient();

$crawler = $client->request('GET','/post/2');
$this->assertResponseIsSuccessful();
$this->assertSelectorTextContains('h1', 'test title 2');
}

}

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store