diff --git a/Service/DependentEntity/DependentEntityService.php b/Service/DependentEntity/DependentEntityService.php index 403d3e8..ec9a402 100644 --- a/Service/DependentEntity/DependentEntityService.php +++ b/Service/DependentEntity/DependentEntityService.php @@ -55,7 +55,7 @@ public function setDependentEntities(DependentEntityInterface $entity): void continue; } - $propertyPath = $attributes[0]->getArguments()['propertypath']; + $propertyPath = $attributes[0]->getArguments()['propertyPath']; $propertyPathValue = $this->propertyAccessor->getValue($entity, $propertyPath); diff --git a/Service/Repository/RepositoryService.php b/Service/Repository/RepositoryService.php index fa1a884..65cf1f0 100644 --- a/Service/Repository/RepositoryService.php +++ b/Service/Repository/RepositoryService.php @@ -33,7 +33,7 @@ public function getEntityById(string $id, string $class): mixed $repository = $this->em->getRepository($class); // @phpstan-ignore-line if (!$repository instanceof GettableOneByIdInterface) { - throw new LogicException(\sprintf('Repository %s should implements %s interface', $repository->getClassName(), GettableOneByIdInterface::class)); + throw new LogicException(\sprintf('Repository %s should implements %s interface', $repository::class, GettableOneByIdInterface::class)); } return $repository->getOneById($id); @@ -50,7 +50,7 @@ public function findEntityById(string $id, string $class): mixed $repository = $this->em->getRepository($class); // @phpstan-ignore-line if (!$repository instanceof FindableByIdInterface) { - throw new LogicException(\sprintf('Repository %s should implements %s interface', $repository->getClassName(), FindableByIdInterface::class)); + throw new LogicException(\sprintf('Repository %s should implements %s interface', $repository::class, FindableByIdInterface::class)); } return $repository->findOneById($id); diff --git a/Tests/Attribute/DependentEntityTest.php b/Tests/Attribute/DependentEntityTest.php new file mode 100644 index 0000000..dffcaf0 --- /dev/null +++ b/Tests/Attribute/DependentEntityTest.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace StfalconStudio\ApiBundle\Tests\Attribute; + +use PHPUnit\Framework\TestCase; +use StfalconStudio\ApiBundle\Attribute\DependentEntity; +use StfalconStudio\ApiBundle\Exception\InvalidArgumentException; + +/** + * DependedEntityTest. + */ +final class DependentEntityTest extends TestCase +{ + public function testNotEmptyPropertyPath(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('The "propertyPath" parameter can not be empty.'); + + new DependentEntity(propertyPath: ''); + } + + public function testGetPropertyPath(): void + { + $propertyPath = 'someField'; + $attribute = new DependentEntity(propertyPath: $propertyPath); + + self::assertSame($propertyPath, $attribute->getPropertyPath()); + } +} diff --git a/Tests/Service/DependentEntity/DependentEntityServiceTest.php b/Tests/Service/DependentEntity/DependentEntityServiceTest.php new file mode 100644 index 0000000..fe472a5 --- /dev/null +++ b/Tests/Service/DependentEntity/DependentEntityServiceTest.php @@ -0,0 +1,126 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace StfalconStudio\ApiBundle\Tests\Service\DependentEntity; + +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use StfalconStudio\ApiBundle\Service\DependentEntity\DependentEntityService; +use StfalconStudio\ApiBundle\Service\Repository\RepositoryService; +use Symfony\Component\PropertyAccess\PropertyAccessor; + +final class DependentEntityServiceTest extends TestCase +{ + /** @var PropertyAccessor|MockObject */ + private PropertyAccessor|MockObject $propertyAccessor; + + /** @var RepositoryService|MockObject */ + private RepositoryService|MockObject $repositoryService; + + private DependentEntityService $dependentEntityService; + + protected function setUp(): void + { + $this->repositoryService = $this->createMock(RepositoryService::class); + $this->propertyAccessor = $this->createMock(PropertyAccessor::class); + $this->dependentEntityService = new DependentEntityService($this->repositoryService); + $this->dependentEntityService->setPropertyAccessor($this->propertyAccessor); + } + + protected function tearDown(): void + { + unset( + $this->repositoryService, + $this->dependentEntityService, + $this->propertyAccessor, + ); + } + + public function testSetDependentEntities(): void + { + $entity = new DummyDependentEntityClass(name: 'some name'); + + $dependentEntity = $this->createMock(DummyDependentEntityClass::class); + + $this->propertyAccessor + ->expects(self::once()) + ->method('getValue') + ->with($entity, 'name') + ->willReturn('some name') + ; + + $this->repositoryService + ->expects(self::once()) + ->method('getEntityById') + ->with('some name', DummyDependentEntityClass::class) + ->willReturn($dependentEntity) + ; + + $this->propertyAccessor + ->expects(self::once()) + ->method('setValue') + ->with($entity, 'dependentEntity', $dependentEntity) + ; + + $this->dependentEntityService->setDependentEntities($entity); + } + + public function testSetNull(): void + { + $entity = new DummyDependentEntityClass(name: 'some name'); + + $this->propertyAccessor + ->expects(self::once()) + ->method('getValue') + ->with($entity, 'name') + ->willReturn(null) + ; + + $this->repositoryService + ->expects(self::never()) + ->method('getEntityById') + ; + + $this->propertyAccessor + ->expects(self::once()) + ->method('setValue') + ->with($entity, 'dependentEntity', null) + ; + + $this->dependentEntityService->setDependentEntities($entity); + } + + public function testEmptyAttribute(): void + { + $entity = new DummyDependentEntityClassEmptyAttribute(name: 'some name'); + + $this->propertyAccessor + ->expects(self::never()) + ->method('getValue') + ->with($entity, 'name') + ->willReturn(null) + ; + + $this->repositoryService + ->expects(self::never()) + ->method('getEntityById') + ; + + $this->propertyAccessor + ->expects(self::never()) + ->method('setValue') + ->with($entity, 'dependentEntity', null) + ; + + $this->dependentEntityService->setDependentEntities($entity); + } +} diff --git a/Tests/Service/DependentEntity/DummyDependentEntityClass.php b/Tests/Service/DependentEntity/DummyDependentEntityClass.php new file mode 100644 index 0000000..0683232 --- /dev/null +++ b/Tests/Service/DependentEntity/DummyDependentEntityClass.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace StfalconStudio\ApiBundle\Tests\Service\DependentEntity; + +use StfalconStudio\ApiBundle\Attribute\DependentEntity; +use StfalconStudio\ApiBundle\Service\DependentEntity\DependentEntityInterface; + +class DummyDependentEntityClass implements DependentEntityInterface +{ + #[DependentEntity(propertyPath: 'name')] + private ?DummyDependentEntityClass $dependentEntity; + + public function __construct(private readonly string $name) + { + } + + public function getName(): string + { + return $this->name; + } + + public function getDependentEntity(): ?DummyDependentEntityClass + { + return $this->dependentEntity; + } + + public function setDependentEntity(?DummyDependentEntityClass $dependentEntity): self + { + $this->dependentEntity = $dependentEntity; + + return $this; + } +} diff --git a/Tests/Service/DependentEntity/DummyDependentEntityClassEmptyAttribute.php b/Tests/Service/DependentEntity/DummyDependentEntityClassEmptyAttribute.php new file mode 100644 index 0000000..16759aa --- /dev/null +++ b/Tests/Service/DependentEntity/DummyDependentEntityClassEmptyAttribute.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace StfalconStudio\ApiBundle\Tests\Service\DependentEntity; + +use StfalconStudio\ApiBundle\Service\DependentEntity\DependentEntityInterface; + +final class DummyDependentEntityClassEmptyAttribute implements DependentEntityInterface +{ + private ?DummyDependentEntityClassEmptyAttribute $dependentEntity; + + public function __construct(private readonly string $name) + { + } + + public function getName(): string + { + return $this->name; + } + + public function getDependentEntity(): ?DummyDependentEntityClassEmptyAttribute + { + return $this->dependentEntity; + } + + public function setDependentEntity(?DummyDependentEntityClassEmptyAttribute $dependentEntity): self + { + $this->dependentEntity = $dependentEntity; + + return $this; + } +} diff --git a/Tests/Service/Repository/DummyRepository.php b/Tests/Service/Repository/DummyRepository.php new file mode 100644 index 0000000..7e53aaf --- /dev/null +++ b/Tests/Service/Repository/DummyRepository.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace StfalconStudio\ApiBundle\Tests\Service\Repository; + +use StfalconStudio\ApiBundle\Service\Repository\FindableByIdInterface; +use StfalconStudio\ApiBundle\Service\Repository\GettableOneByIdInterface; + +class DummyRepository implements GettableOneByIdInterface, FindableByIdInterface +{ + public function findOneById(string $id): mixed + { + return null; + } + + public function getOneById(string $id): mixed + { + return null; + } +} diff --git a/Tests/Service/Repository/DummyRepositoryWithOutInterface.php b/Tests/Service/Repository/DummyRepositoryWithOutInterface.php new file mode 100644 index 0000000..1677bca --- /dev/null +++ b/Tests/Service/Repository/DummyRepositoryWithOutInterface.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace StfalconStudio\ApiBundle\Tests\Service\Repository; + +class DummyRepositoryWithOutInterface +{ +} diff --git a/Tests/Service/Repository/RepositoryServiceTest.php b/Tests/Service/Repository/RepositoryServiceTest.php new file mode 100644 index 0000000..55f29e7 --- /dev/null +++ b/Tests/Service/Repository/RepositoryServiceTest.php @@ -0,0 +1,130 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace StfalconStudio\ApiBundle\Tests\Service\Repository; + +use Doctrine\ORM\EntityManager; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use StfalconStudio\ApiBundle\Exception\LogicException; +use StfalconStudio\ApiBundle\Service\Repository\RepositoryService; + +final class RepositoryServiceTest extends TestCase +{ + /** @var EntityManager|MockObject */ + private EntityManager|MockObject $entityManager; + + private RepositoryService $repositoryService; + + protected function setUp(): void + { + $this->entityManager = $this->createMock(EntityManager::class); + $this->repositoryService = new RepositoryService(); + $this->repositoryService->setEntityManager($this->entityManager); + } + + protected function tearDown(): void + { + unset( + $this->repositoryService, + $this->entityManager, + ); + } + + public function testGetEntityById(): void + { + $id = '123'; + $class = 'someClassName'; + $repository = $this->createMock(DummyRepository::class); + + $entity = new \stdClass(); + + $this->entityManager + ->expects(self::once()) + ->method('getRepository') + ->with($class) + ->willReturn($repository) + ; + + $repository + ->expects(self::once()) + ->method('getOneById') + ->with($id) + ->willReturn($entity) + ; + + $result = $this->repositoryService->getEntityById($id, $class); + self::assertSame($result, $entity); + } + + public function testFindEntityById(): void + { + $id = '123'; + $class = 'someClassName'; + $repository = $this->createMock(DummyRepository::class); + + $entity = new \stdClass(); + + $this->entityManager + ->expects(self::once()) + ->method('getRepository') + ->with($class) + ->willReturn($repository) + ; + + $repository + ->expects(self::once()) + ->method('findOneById') + ->with($id) + ->willReturn($entity) + ; + + $result = $this->repositoryService->findEntityById($id, $class); + self::assertSame($result, $entity); + } + + public function testGetEntityByIdException(): void + { + $id = '123'; + $class = 'someClassName'; + $repository = $this->createMock(DummyRepositoryWithOutInterface::class); + + $this->entityManager + ->expects(self::once()) + ->method('getRepository') + ->with($class) + ->willReturn($repository) + ; + + $this->expectException(LogicException::class); + + $this->repositoryService->getEntityById($id, $class); + } + + public function testFindEntityByIdException(): void + { + $id = '123'; + $class = 'someClassName'; + $repository = $this->createMock(DummyRepositoryWithOutInterface::class); + + $this->entityManager + ->expects(self::once()) + ->method('getRepository') + ->with($class) + ->willReturn($repository) + ; + + $this->expectException(LogicException::class); + + $this->repositoryService->findEntityById($id, $class); + } +}