diff --git a/config/packages/doctrine.php b/config/packages/doctrine.php index dd89d43..d31c353 100644 --- a/config/packages/doctrine.php +++ b/config/packages/doctrine.php @@ -10,6 +10,7 @@ [ 'dbal' => [ 'url' => '%env(resolve:DATABASE_URL)%', + 'use_savepoints' => true, ], 'orm' => [ 'report_fields_where_declared' => true, diff --git a/config/packages/messenger.php b/config/packages/messenger.php index d32f87f..8f9bc2a 100644 --- a/config/packages/messenger.php +++ b/config/packages/messenger.php @@ -11,11 +11,7 @@ 'messenger' => [ 'default_bus' => 'command.bus', 'buses' => [ - 'command.bus' => [ - 'middleware' => [ - 'messenger.middleware.doctrine_transaction', - ], - ], + 'command.bus' => [], 'query.bus' => [], ], 'transports' => [ @@ -27,4 +23,18 @@ ], ], ]); + + if ('test' !== $containerConfigurator->env()) { + $containerConfigurator->extension('framework', [ + 'messenger' => [ + 'buses' => [ + 'command.bus' => [ + 'middleware' => [ + 'messenger.middleware.doctrine_transaction', + ], + ], + ], + ], + ]); + } }; diff --git a/src/BookStore/Application/Command/CreateBookCommandHandler.php b/src/BookStore/Application/Command/CreateBookCommandHandler.php index a49b4a5..872df1b 100644 --- a/src/BookStore/Application/Command/CreateBookCommandHandler.php +++ b/src/BookStore/Application/Command/CreateBookCommandHandler.php @@ -25,7 +25,7 @@ public function __invoke(CreateBookCommand $command): Book $command->price, ); - $this->bookRepository->save($book); + $this->bookRepository->add($book); return $book; } diff --git a/src/BookStore/Domain/Repository/BookRepositoryInterface.php b/src/BookStore/Domain/Repository/BookRepositoryInterface.php index ad53742..d71215d 100644 --- a/src/BookStore/Domain/Repository/BookRepositoryInterface.php +++ b/src/BookStore/Domain/Repository/BookRepositoryInterface.php @@ -14,7 +14,7 @@ */ interface BookRepositoryInterface extends RepositoryInterface { - public function save(Book $book): void; + public function add(Book $book): void; public function remove(Book $book): void; diff --git a/src/BookStore/Infrastructure/Doctrine/DoctrineBookRepository.php b/src/BookStore/Infrastructure/Doctrine/DoctrineBookRepository.php index f139cf1..2ff47b5 100644 --- a/src/BookStore/Infrastructure/Doctrine/DoctrineBookRepository.php +++ b/src/BookStore/Infrastructure/Doctrine/DoctrineBookRepository.php @@ -25,7 +25,7 @@ public function __construct(EntityManagerInterface $em) parent::__construct($em, self::ENTITY_CLASS, self::ALIAS); } - public function save(Book $book): void + public function add(Book $book): void { $this->em->persist($book); } diff --git a/src/BookStore/Infrastructure/InMemory/InMemoryBookRepository.php b/src/BookStore/Infrastructure/InMemory/InMemoryBookRepository.php index c3aadfc..9afacd5 100644 --- a/src/BookStore/Infrastructure/InMemory/InMemoryBookRepository.php +++ b/src/BookStore/Infrastructure/InMemory/InMemoryBookRepository.php @@ -15,7 +15,7 @@ */ final class InMemoryBookRepository extends InMemoryRepository implements BookRepositoryInterface { - public function save(Book $book): void + public function add(Book $book): void { $this->entities[(string) $book->id()] = $book; } diff --git a/tests/BookStore/Acceptance/AnonymizeBooksTest.php b/tests/BookStore/Acceptance/AnonymizeBooksTest.php index 899f581..05d56fb 100644 --- a/tests/BookStore/Acceptance/AnonymizeBooksTest.php +++ b/tests/BookStore/Acceptance/AnonymizeBooksTest.php @@ -19,7 +19,7 @@ public function testAnonymizeAuthorOfBooks(): void $bookRepository = static::getContainer()->get(BookRepositoryInterface::class); for ($i = 0; $i < 10; ++$i) { - $bookRepository->save(DummyBookFactory::createBook(author: sprintf('author_%d', $i))); + $bookRepository->add(DummyBookFactory::createBook(author: sprintf('author_%d', $i))); } $response = $client->request('POST', '/api/books/anonymize', [ diff --git a/tests/BookStore/Acceptance/BookCrudTest.php b/tests/BookStore/Acceptance/BookCrudTest.php index 75c8eff..f6b6606 100644 --- a/tests/BookStore/Acceptance/BookCrudTest.php +++ b/tests/BookStore/Acceptance/BookCrudTest.php @@ -26,7 +26,7 @@ public function testReturnPaginatedBooks(): void $bookRepository = static::getContainer()->get(BookRepositoryInterface::class); for ($i = 0; $i < 100; ++$i) { - $bookRepository->save(DummyBookFactory::createBook()); + $bookRepository->add(DummyBookFactory::createBook()); } $client->request('GET', '/api/books'); @@ -51,9 +51,9 @@ public function testFilterBooksByAuthor(): void /** @var BookRepositoryInterface $bookRepository */ $bookRepository = static::getContainer()->get(BookRepositoryInterface::class); - $bookRepository->save(DummyBookFactory::createBook(author: 'authorOne')); - $bookRepository->save(DummyBookFactory::createBook(author: 'authorOne')); - $bookRepository->save(DummyBookFactory::createBook(author: 'authorTwo')); + $bookRepository->add(DummyBookFactory::createBook(author: 'authorOne')); + $bookRepository->add(DummyBookFactory::createBook(author: 'authorOne')); + $bookRepository->add(DummyBookFactory::createBook(author: 'authorTwo')); $client->request('GET', '/api/books?author=authorOne'); @@ -83,7 +83,7 @@ public function testReturnBook(): void content: 'content', price: 1000, ); - $bookRepository->save($book); + $bookRepository->add($book); $client->request('GET', sprintf('/api/books/%s', (string) $book->id())); @@ -186,7 +186,7 @@ public function testUpdateBook(): void $bookRepository = static::getContainer()->get(BookRepositoryInterface::class); $book = DummyBookFactory::createBook(); - $bookRepository->save($book); + $bookRepository->add($book); $client->request('PUT', sprintf('/api/books/%s', $book->id()), [ 'json' => [ @@ -227,7 +227,7 @@ public function testPartiallyUpdateBook(): void $bookRepository = static::getContainer()->get(BookRepositoryInterface::class); $book = DummyBookFactory::createBook(name: 'name', description: 'description'); - $bookRepository->save($book); + $bookRepository->add($book); $client->request('PATCH', sprintf('/api/books/%s', $book->id()), [ 'headers' => [ @@ -260,7 +260,7 @@ public function testDeleteBook(): void $bookRepository = static::getContainer()->get(BookRepositoryInterface::class); $book = DummyBookFactory::createBook(); - $bookRepository->save($book); + $bookRepository->add($book); $response = $client->request('DELETE', sprintf('/api/books/%s', $book->id())); diff --git a/tests/BookStore/Acceptance/CheapestBooksTest.php b/tests/BookStore/Acceptance/CheapestBooksTest.php index 07f22ff..40e7858 100644 --- a/tests/BookStore/Acceptance/CheapestBooksTest.php +++ b/tests/BookStore/Acceptance/CheapestBooksTest.php @@ -19,7 +19,7 @@ public function testReturnOnlyTheTenCheapestBooks(): void $bookRepository = static::getContainer()->get(BookRepositoryInterface::class); for ($i = 0; $i < 20; ++$i) { - $bookRepository->save(DummyBookFactory::createBook(price: $i)); + $bookRepository->add(DummyBookFactory::createBook(price: $i)); } $response = $client->request('GET', '/api/books/cheapest'); @@ -46,7 +46,7 @@ public function testReturnBooksSortedByPrice(): void $prices = [2000, 1000, 3000]; foreach ($prices as $price) { - $bookRepository->save(DummyBookFactory::createBook(price: $price)); + $bookRepository->add(DummyBookFactory::createBook(price: $price)); } $response = $client->request('GET', '/api/books/cheapest'); diff --git a/tests/BookStore/Acceptance/DiscountBookTest.php b/tests/BookStore/Acceptance/DiscountBookTest.php index 31bc118..2df1f21 100644 --- a/tests/BookStore/Acceptance/DiscountBookTest.php +++ b/tests/BookStore/Acceptance/DiscountBookTest.php @@ -20,7 +20,7 @@ public function testApplyADiscountOnBook(): void $bookRepository = static::getContainer()->get(BookRepositoryInterface::class); $book = DummyBookFactory::createBook(price: 1000); - $bookRepository->save($book); + $bookRepository->add($book); $client->request('POST', sprintf('/api/books/%s/discount', $book->id()), [ 'json' => [ @@ -43,7 +43,7 @@ public function testValidateDiscountAmount(): void $bookRepository = static::getContainer()->get(BookRepositoryInterface::class); $book = DummyBookFactory::createBook(price: 1000); - $bookRepository->save($book); + $bookRepository->add($book); $client->request('POST', sprintf('/api/books/%s/discount', $book->id()), [ 'json' => [ diff --git a/tests/BookStore/Functional/AnonymizeBooksTest.php b/tests/BookStore/Functional/AnonymizeBooksTest.php index 1ec2d8f..67181ee 100644 --- a/tests/BookStore/Functional/AnonymizeBooksTest.php +++ b/tests/BookStore/Functional/AnonymizeBooksTest.php @@ -22,7 +22,7 @@ public function testAnonymizeAuthorOfBooks(): void $commandBus = static::getContainer()->get(CommandBusInterface::class); for ($i = 0; $i < 10; ++$i) { - $bookRepository->save(DummyBookFactory::createBook(author: sprintf('author_%d', $i))); + $bookRepository->add(DummyBookFactory::createBook(author: sprintf('author_%d', $i))); } $commandBus->dispatch(new AnonymizeBooksCommand('anon.')); diff --git a/tests/BookStore/Functional/DeleteBookTest.php b/tests/BookStore/Functional/DeleteBookTest.php index ac9cfa6..c62fba7 100644 --- a/tests/BookStore/Functional/DeleteBookTest.php +++ b/tests/BookStore/Functional/DeleteBookTest.php @@ -21,7 +21,7 @@ public function testDeleteBook(): void $commandBus = static::getContainer()->get(CommandBusInterface::class); $book = DummyBookFactory::createBook(); - $bookRepository->save($book); + $bookRepository->add($book); static::assertCount(1, $bookRepository); diff --git a/tests/BookStore/Functional/DiscountBookTest.php b/tests/BookStore/Functional/DiscountBookTest.php index e74c77a..ec0ae48 100644 --- a/tests/BookStore/Functional/DiscountBookTest.php +++ b/tests/BookStore/Functional/DiscountBookTest.php @@ -26,7 +26,7 @@ public function testApplyADiscountOnBook(int $initialAmount, int $discount, int $commandBus = static::getContainer()->get(CommandBusInterface::class); $book = DummyBookFactory::createBook(price: $initialAmount); - $bookRepository->save($book); + $bookRepository->add($book); $commandBus->dispatch(new DiscountBookCommand($book->id(), new Discount($discount))); diff --git a/tests/BookStore/Functional/FindBookTest.php b/tests/BookStore/Functional/FindBookTest.php index 310935d..3529509 100644 --- a/tests/BookStore/Functional/FindBookTest.php +++ b/tests/BookStore/Functional/FindBookTest.php @@ -21,7 +21,7 @@ public function testFindBook(): void $queryBus = static::getContainer()->get(QueryBusInterface::class); $book = DummyBookFactory::createBook(); - $bookRepository->save($book); + $bookRepository->add($book); static::assertSame($book, $queryBus->ask(new FindBookQuery($book->id()))); } diff --git a/tests/BookStore/Functional/FindBooksTest.php b/tests/BookStore/Functional/FindBooksTest.php index 0547760..7b3e87a 100644 --- a/tests/BookStore/Functional/FindBooksTest.php +++ b/tests/BookStore/Functional/FindBooksTest.php @@ -30,7 +30,7 @@ public function testFindBooks(): void ]; foreach ($initialBooks as $book) { - $bookRepository->save($book); + $bookRepository->add($book); } $books = $queryBus->ask(new FindBooksQuery()); @@ -49,9 +49,9 @@ public function testFilterBooksByAuthor(): void /** @var QueryBusInterface $queryBus */ $queryBus = static::getContainer()->get(QueryBusInterface::class); - $bookRepository->save(DummyBookFactory::createBook(author: 'authorOne')); - $bookRepository->save(DummyBookFactory::createBook(author: 'authorOne')); - $bookRepository->save(DummyBookFactory::createBook(author: 'authorTwo')); + $bookRepository->add(DummyBookFactory::createBook(author: 'authorOne')); + $bookRepository->add(DummyBookFactory::createBook(author: 'authorOne')); + $bookRepository->add(DummyBookFactory::createBook(author: 'authorTwo')); static::assertCount(3, $bookRepository); @@ -80,7 +80,7 @@ public function testReturnPaginatedBooks(): void ]; foreach ($initialBooks as $book) { - $bookRepository->save($book); + $bookRepository->add($book); } $books = $queryBus->ask(new FindBooksQuery(page: 2, itemsPerPage: 2)); diff --git a/tests/BookStore/Functional/FindCheapestBooksTest.php b/tests/BookStore/Functional/FindCheapestBooksTest.php index fc54f01..44bda1f 100644 --- a/tests/BookStore/Functional/FindCheapestBooksTest.php +++ b/tests/BookStore/Functional/FindCheapestBooksTest.php @@ -22,7 +22,7 @@ public function testReturnOnlyTheCheapestBooks(): void $queryBus = static::getContainer()->get(QueryBusInterface::class); for ($i = 0; $i < 5; ++$i) { - $bookRepository->save(DummyBookFactory::createBook()); + $bookRepository->add(DummyBookFactory::createBook()); } $cheapestBooks = $queryBus->ask(new FindCheapestBooksQuery(3)); @@ -40,7 +40,7 @@ public function testReturnBooksSortedByPrice(): void $prices = [2000, 1000, 3000]; foreach ($prices as $price) { - $bookRepository->save(DummyBookFactory::createBook(price: $price)); + $bookRepository->add(DummyBookFactory::createBook(price: $price)); } $cheapestBooks = $queryBus->ask(new FindCheapestBooksQuery(3)); diff --git a/tests/BookStore/Functional/UpdateBookTest.php b/tests/BookStore/Functional/UpdateBookTest.php index f3fac6a..f334a03 100644 --- a/tests/BookStore/Functional/UpdateBookTest.php +++ b/tests/BookStore/Functional/UpdateBookTest.php @@ -33,7 +33,7 @@ public function testUpdateBook(): void price: 1000, ); - $bookRepository->save($initialBook); + $bookRepository->add($initialBook); $commandBus->dispatch(new UpdateBookCommand( $initialBook->id(), diff --git a/tests/BookStore/Integration/Doctrine/DoctrineBookRepositoryTest.php b/tests/BookStore/Integration/Doctrine/DoctrineBookRepositoryTest.php index 8b96a10..f5bf4d0 100644 --- a/tests/BookStore/Integration/Doctrine/DoctrineBookRepositoryTest.php +++ b/tests/BookStore/Integration/Doctrine/DoctrineBookRepositoryTest.php @@ -18,12 +18,14 @@ final class DoctrineBookRepositoryTest extends KernelTestCase { private static Connection $connection; + private static EntityManagerInterface $em; public static function setUpBeforeClass(): void { parent::setUpBeforeClass(); static::$connection = static::getContainer()->get(Connection::class); + static::$em = static::getContainer()->get(EntityManagerInterface::class); (new Application(static::$kernel)) ->find('doctrine:database:create') @@ -47,7 +49,7 @@ public function testSave(): void static::assertEmpty($repository); $book = DummyBookFactory::createBook(); - $repository->save($book); + self::$em->wrapInTransaction(fn () => $repository->add($book)); static::assertCount(1, $repository); } @@ -58,11 +60,11 @@ public function testRemove(): void $repository = static::getContainer()->get(DoctrineBookRepository::class); $book = DummyBookFactory::createBook(); - $repository->save($book); + self::$em->wrapInTransaction(fn () => $repository->add($book)); static::assertCount(1, $repository); - $repository->remove($book); + self::$em->wrapInTransaction(fn () => $repository->remove($book)); static::assertEmpty($repository); } @@ -74,7 +76,7 @@ public function testOfId(): void static::assertEmpty($repository); $book = DummyBookFactory::createBook(); - $repository->save($book); + self::$em->wrapInTransaction(fn () => $repository->add($book)); static::getContainer()->get(EntityManagerInterface::class)->clear(); @@ -86,9 +88,11 @@ public function testWithAuthor(): void /** @var DoctrineBookRepository $repository */ $repository = static::getContainer()->get(DoctrineBookRepository::class); - $repository->save(DummyBookFactory::createBook(author: 'authorOne')); - $repository->save(DummyBookFactory::createBook(author: 'authorOne')); - $repository->save(DummyBookFactory::createBook(author: 'authorTwo')); + self::$em->wrapInTransaction(function () use ($repository) { + $repository->add(DummyBookFactory::createBook(author: 'authorOne')); + $repository->add(DummyBookFactory::createBook(author: 'authorOne')); + $repository->add(DummyBookFactory::createBook(author: 'authorTwo')); + }); static::assertCount(2, $repository->withAuthor(new Author('authorOne'))); static::assertCount(1, $repository->withAuthor(new Author('authorTwo'))); @@ -99,9 +103,11 @@ public function testWithCheapestsFirst(): void /** @var DoctrineBookRepository $repository */ $repository = static::getContainer()->get(DoctrineBookRepository::class); - $repository->save(DummyBookFactory::createBook(price: 1)); - $repository->save(DummyBookFactory::createBook(price: 3)); - $repository->save(DummyBookFactory::createBook(price: 2)); + self::$em->wrapInTransaction(function () use ($repository) { + $repository->add(DummyBookFactory::createBook(price: 1)); + $repository->add(DummyBookFactory::createBook(price: 3)); + $repository->add(DummyBookFactory::createBook(price: 2)); + }); $prices = []; foreach ($repository->withCheapestsFirst() as $book) { @@ -143,9 +149,11 @@ public function testIteratorWithoutPagination(): void DummyBookFactory::createBook(), DummyBookFactory::createBook(), ]; - foreach ($books as $book) { - $repository->save($book); - } + self::$em->wrapInTransaction(function () use ($books, $repository) { + foreach ($books as $book) { + $repository->add($book); + } + }); $i = 0; foreach ($repository as $book) { @@ -167,7 +175,7 @@ public function testIteratorWithPagination(): void ]; foreach ($books as $book) { - $repository->save($book); + $repository->add($book); } $repository = $repository->withPagination(1, 2); @@ -202,7 +210,7 @@ public function testCount(): void DummyBookFactory::createBook(), ]; foreach ($books as $book) { - $repository->save($book); + $repository->add($book); } static::assertCount(count($books), $repository); diff --git a/tests/BookStore/Integration/InMemory/InMemoryBookRepositoryTest.php b/tests/BookStore/Integration/InMemory/InMemoryBookRepositoryTest.php index 8ce1382..25b760c 100644 --- a/tests/BookStore/Integration/InMemory/InMemoryBookRepositoryTest.php +++ b/tests/BookStore/Integration/InMemory/InMemoryBookRepositoryTest.php @@ -20,7 +20,7 @@ public function testAdd(): void static::assertEmpty($repository); $book = DummyBookFactory::createBook(); - $repository->save($book); + $repository->add($book); static::assertCount(1, $repository); } @@ -31,7 +31,7 @@ public function testRemove(): void $repository = static::getContainer()->get(InMemoryBookRepository::class); $book = DummyBookFactory::createBook(); - $repository->save($book); + $repository->add($book); static::assertCount(1, $repository); @@ -47,7 +47,7 @@ public function testOfId(): void static::assertEmpty($repository); $book = DummyBookFactory::createBook(); - $repository->save($book); + $repository->add($book); static::assertSame($book, $repository->ofId($book->id())); } @@ -57,9 +57,9 @@ public function testWithAuthor(): void /** @var InMemoryBookRepository $repository */ $repository = static::getContainer()->get(InMemoryBookRepository::class); - $repository->save(DummyBookFactory::createBook(author: 'authorOne')); - $repository->save(DummyBookFactory::createBook(author: 'authorOne')); - $repository->save(DummyBookFactory::createBook(author: 'authorTwo')); + $repository->add(DummyBookFactory::createBook(author: 'authorOne')); + $repository->add(DummyBookFactory::createBook(author: 'authorOne')); + $repository->add(DummyBookFactory::createBook(author: 'authorTwo')); static::assertCount(2, $repository->withAuthor(new Author('authorOne'))); static::assertCount(1, $repository->withAuthor(new Author('authorTwo'))); @@ -70,9 +70,9 @@ public function testWithCheapestsFirst(): void /** @var InMemoryBookRepository $repository */ $repository = static::getContainer()->get(InMemoryBookRepository::class); - $repository->save(DummyBookFactory::createBook(price: 1)); - $repository->save(DummyBookFactory::createBook(price: 3)); - $repository->save(DummyBookFactory::createBook(price: 2)); + $repository->add(DummyBookFactory::createBook(price: 1)); + $repository->add(DummyBookFactory::createBook(price: 3)); + $repository->add(DummyBookFactory::createBook(price: 2)); $prices = []; foreach ($repository->withCheapestsFirst() as $book) { @@ -115,7 +115,7 @@ public function testIteratorWithoutPagination(): void DummyBookFactory::createBook(), ]; foreach ($books as $book) { - $repository->save($book); + $repository->add($book); } $i = 0; @@ -137,7 +137,7 @@ public function testIteratorWithPagination(): void DummyBookFactory::createBook(), ]; foreach ($books as $book) { - $repository->save($book); + $repository->add($book); } $repository = $repository->withPagination(1, 2); @@ -172,7 +172,7 @@ public function testCount(): void DummyBookFactory::createBook(), ]; foreach ($books as $book) { - $repository->save($book); + $repository->add($book); } static::assertCount(count($books), $repository);