Skip to content

Commit

Permalink
tests: Improve coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
Pixelshaped committed Jul 22, 2024
1 parent 508d436 commit 0c26922
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 71 deletions.
10 changes: 3 additions & 7 deletions src/FlatMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ private function createMappingRecursive(string $dtoClassName, array& $objectIden
public function map(string $dtoClassName, iterable $data): array {

$this->createMapping($dtoClassName);

$objectsMap = [];
$referencesMap = [];
foreach ($data as $row) {
Expand Down Expand Up @@ -206,12 +206,8 @@ private function linkObjects(array $referencesMap, array $objectsMap): void
foreach ($references as $identifier => $foreignObjects) {
foreach ($foreignObjects as $mappedProperty => $foreignObjectIdentifiers) {
if (isset($objectsMap[$objectClass][$identifier])) {
try {
$reflectionClass = new ReflectionClass($objectClass);
$arrayProperty = $reflectionClass->getProperty($mappedProperty);
} catch (\ReflectionException $e) {
throw new MappingException($e->getMessage(), $e->getCode(), $e);
}
$reflectionClass = new ReflectionClass($objectClass);
$arrayProperty = $reflectionClass->getProperty($mappedProperty);
$arrayProperty->setValue($objectsMap[$objectClass][$identifier], $foreignObjectIdentifiers);
}
}
Expand Down
89 changes: 89 additions & 0 deletions tests/FlatMapperCreateMappingTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php
declare(strict_types=1);

namespace Pixelshaped\FlatMapperBundle\Tests;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\CoversMethod;
use PHPUnit\Framework\TestCase;
use Pixelshaped\FlatMapperBundle\Exception\MappingCreationException;
use Pixelshaped\FlatMapperBundle\FlatMapper;
use Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid\RootDTO as InvalidRootDTO;
use Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid\RootDTOWithEmptyClassIdentifier;
use Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid\RootDTOWithNoIdentifier;
use Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid\RootDTOWithoutConstructor;
use Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid\RootDTOWithTooManyIdentifiers;
use Pixelshaped\FlatMapperBundle\Tests\Examples\Valid\ColumnArray\ColumnArrayDTO;
use Pixelshaped\FlatMapperBundle\Tests\Examples\Valid\ReferencesArray\AuthorDTO;
use Symfony\Contracts\Cache\CacheInterface;

#[CoversMethod(FlatMapper::class, 'createMapping')]
#[CoversMethod(FlatMapper::class, 'createMappingRecursive')]
#[CoversMethod(FlatMapper::class, 'setCacheService')]
#[CoversClass(MappingCreationException::class)]
class FlatMapperCreateMappingTest extends TestCase
{
public function testCreateMappingWithValidDTOsDoesNotAssert(): void
{
$this->expectNotToPerformAssertions();
(new FlatMapper())->createMapping(ColumnArrayDTO::class);
(new FlatMapper())->createMapping(AuthorDTO::class);
}

public function testCreateMappingWithCacheServiceDoesNotAssert(): void
{
$flatMapper = new FlatMapper();
$reflectionMethod = (new \ReflectionClass(FlatMapper::class))->getMethod('createMappingRecursive');
$reflectionMethod->setAccessible(true);

$cacheInterface = $this->createMock(CacheInterface::class);
$cacheInterface->expects($this->once())->method('get')->willReturn(
$reflectionMethod->invoke($flatMapper, AuthorDTO::class)
);

$flatMapper->setCacheService($cacheInterface);
$flatMapper->createMapping(AuthorDTO::class);
}

public function testCreateMappingWrongClassNameAsserts(): void
{
$this->expectException(MappingCreationException::class);
$this->expectExceptionMessageMatches("/An error occurred during mapping creation: ThisIsNotAValidClassString is not a valid class name/");
(new FlatMapper())->createMapping('ThisIsNotAValidClassString');
}

public function testCreateMappingWithSeveralIdenticalIdentifiersAsserts(): void
{
$this->expectException(MappingCreationException::class);
$this->expectExceptionMessageMatches("/Several data identifiers are identical/");
(new FlatMapper())->createMapping(InvalidRootDTO::class);
}

public function testCreateMappingWithTooManyIdentifiersAsserts(): void
{
$this->expectException(MappingCreationException::class);
$this->expectExceptionMessageMatches("/does not contain exactly one #\[Identifier\] attribute/");
(new FlatMapper())->createMapping(RootDTOWithTooManyIdentifiers::class);
}

public function testCreateMappingWithNoIdentifierAsserts(): void
{
$this->expectException(MappingCreationException::class);
$this->expectExceptionMessageMatches("/does not contain exactly one #\[Identifier\] attribute/");
(new FlatMapper())->createMapping(RootDTOWithNoIdentifier::class);
}

public function testCreateMappingWithNoConstructorAsserts(): void
{
$this->expectException(MappingCreationException::class);
$this->expectExceptionMessageMatches("/does not have a constructor/");
(new FlatMapper())->createMapping(RootDTOWithoutConstructor::class);
}

public function testCreateMappingWithEmptyClassIdentifierAsserts(): void
{
$this->expectException(MappingCreationException::class);
$this->expectExceptionMessageMatches("/The Identifier attribute cannot be used without a property name when used as a Class attribute/");
(new FlatMapper())->createMapping(RootDTOWithEmptyClassIdentifier::class);
}
}
79 changes: 15 additions & 64 deletions tests/FlatMapperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,8 @@

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;
use Pixelshaped\FlatMapperBundle\Exception\MappingCreationException;
use Pixelshaped\FlatMapperBundle\Exception\MappingException;
use Pixelshaped\FlatMapperBundle\FlatMapper;
use Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid\RootDTO as InvalidRootDTO;
use Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid\RootDTOWithEmptyClassIdentifier;
use Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid\RootDTOWithNoIdentifier;
use Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid\RootDTOWithoutConstructor;
use Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid\RootDTOWithTooManyIdentifiers;
use Pixelshaped\FlatMapperBundle\Tests\Examples\Valid\ColumnArray\ColumnArrayDTO;
use Pixelshaped\FlatMapperBundle\Tests\Examples\Valid\Complex\CustomerDTO;
use Pixelshaped\FlatMapperBundle\Tests\Examples\Valid\Complex\InvoiceDTO;
Expand All @@ -23,65 +17,8 @@

#[CoversClass(FlatMapper::class)]
#[CoversClass(MappingException::class)]
#[CoversClass(MappingCreationException::class)]
class FlatMapperTest extends TestCase
{
public function testCreateMappingWithValidDTOsDoesNotAssert(): void
{
$this->expectNotToPerformAssertions();
$mapper = new FlatMapper();
$mapper->createMapping(ColumnArrayDTO::class);
$mapper->createMapping(AuthorDTO::class);
}

public function testCreateMappingWrongClassNameAsserts(): void
{
$this->expectException(MappingCreationException::class);
$this->expectExceptionMessageMatches("/An error occurred during mapping creation: ThisIsNotAValidClassString is not a valid class name/");
$mapper = new FlatMapper();
$mapper->createMapping('ThisIsNotAValidClassString');
}

public function testCreateMappingWithSeveralIdenticalIdentifiersAsserts(): void
{
$this->expectException(MappingCreationException::class);
$this->expectExceptionMessageMatches("/Several data identifiers are identical/");
$mapper = new FlatMapper();
$mapper->createMapping(InvalidRootDTO::class);
}

public function testCreateMappingWithTooManyIdentifiersAsserts(): void
{
$this->expectException(MappingCreationException::class);
$this->expectExceptionMessageMatches("/does not contain exactly one #\[Identifier\] attribute/");
$mapper = new FlatMapper();
$mapper->createMapping(RootDTOWithTooManyIdentifiers::class);
}

public function testCreateMappingWithNoIdentifierAsserts(): void
{
$this->expectException(MappingCreationException::class);
$this->expectExceptionMessageMatches("/does not contain exactly one #\[Identifier\] attribute/");
$mapper = new FlatMapper();
$mapper->createMapping(RootDTOWithNoIdentifier::class);
}

public function testCreateMappingWithNoConstructorAsserts(): void
{
$this->expectException(MappingCreationException::class);
$this->expectExceptionMessageMatches("/does not have a constructor/");
$mapper = new FlatMapper();
$mapper->createMapping(RootDTOWithoutConstructor::class);
}

public function testCreateMappingWithEmptyClassIdentifierAsserts(): void
{
$this->expectException(MappingCreationException::class);
$this->expectExceptionMessageMatches("/The Identifier attribute cannot be used without a property name when used as a Class attribute/");
$mapper = new FlatMapper();
$mapper->createMapping(RootDTOWithEmptyClassIdentifier::class);
}

public function testMappingDataWithMissingIdentifierPropertyAsserts(): void
{
$this->expectException(MappingException::class);
Expand Down Expand Up @@ -138,6 +75,20 @@ public function testMappingDataWithMissingPropertyAsserts(): void
((new FlatMapper())->map(AuthorDTO::class, $results));
}

public function testMappingDataWithBadConstructorTypeAsserts(): void
{
$this->expectException(MappingException::class);
$this->expectExceptionMessageMatches('/An error occurred during mapping: Cannot construct object/');

$results = [
['author_id' => 1, 'author_name' => 'Alice Brian', 'book_id' => 1, 'book_name' => null, 'book_publisher_name' => 'TravelBooks'],
['author_id' => 1, 'author_name' => 'Alice Brian', 'book_id' => 2, 'book_name' => 'My journeys', 'book_publisher_name' => 'Lorem Press'],
['author_id' => 2, 'author_name' => 'Bob Schmo', 'book_id' => 1, 'book_name' => null, 'book_publisher_name' => 'TravelBooks'],
];

((new FlatMapper())->map(AuthorDTO::class, $results));
}

public function testMapValidNestedDTOs(): void
{
$results = [
Expand Down Expand Up @@ -271,4 +222,4 @@ public function testMapEmptyData(): void
var_export([], true)
);
}
}
}

0 comments on commit 0c26922

Please sign in to comment.