Skip to content

Commit b3bb957

Browse files
committed
up mutation tests
1 parent 20922b1 commit b3bb957

13 files changed

+163
-42
lines changed

composer.json

+9
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,14 @@
5656
"phpcbf": "./vendor/bin/phpcbf --standard=./phpcs.xml -n --no-cache -s",
5757
"coverage": "./vendor/phpunit/phpunit/phpunit --configuration ./phpunit.xml --coverage-text --colors=never --coverage-clover coverage.xml",
5858
"coverage-html": "./vendor/phpunit/phpunit/phpunit --configuration ./phpunit.xml --coverage-html public/coverage --coverage-text"
59+
},
60+
"scripts-descriptions": {
61+
"phpunit": "Run tests",
62+
"infection": "Run mutation tests",
63+
"infection-html": "Generate mutation tests report",
64+
"psalm": "Run static analyze",
65+
"phpcs": "Checking codestyle",
66+
"coverage": "Checking code coverage",
67+
"coverage-html": "Generate code coverage report"
5968
}
6069
}

src/CacheGenerator/CacheGenerator.php

+13-8
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public static function create(string $class, HydratorConfig $config = null): Cac
6868
*/
6969
public function getClass(): CacheReflectionClass
7070
{
71+
/** @infection-ignore-all */
7172
if (!$this->cacheExists()) {
7273
$classCache = $this->generate();
7374
} else {
@@ -91,7 +92,7 @@ public function generate(): array
9192
$cache = [
9293
'properties' => array_map(fn($el) => $this->convertToCacheProperty(new RuntimeReflectionProperty($el)), $properties)
9394
];
94-
95+
9596
file_put_contents($this->path, serialize($cache));
9697
return $cache;
9798
}
@@ -104,7 +105,7 @@ public function generate(): array
104105
private function convertToCacheProperty(RuntimeReflectionProperty $property): CacheReflectionProperty
105106
{
106107
$args = $this->getArguments($property);
107-
108+
108109
return new CacheReflectionProperty(
109110
$property->class,
110111
$property->name,
@@ -116,14 +117,15 @@ private function convertToCacheProperty(RuntimeReflectionProperty $property): Ca
116117
$this->getAliases($args),
117118
);
118119
}
120+
119121
/**
120122
* @return array<string>
121123
*/
122-
public function getAliases( $args): array
124+
public function getAliases($args): array
123125
{
124126
$aliases = $args[FieldAlias::class] ?? null;
125-
126-
if (empty($aliases)) {
127+
128+
if (empty($aliases) || !is_array($aliases)) {
127129
return [];
128130
}
129131

@@ -134,7 +136,7 @@ public function getAliases( $args): array
134136
}
135137
return $aliases;
136138
}
137-
139+
138140
/**
139141
* @param RuntimeReflectionProperty $property
140142
*
@@ -175,8 +177,11 @@ public function cacheExists(): bool
175177
private function makeCacheDir(): void
176178
{
177179
if (
178-
!file_exists($this->config->cachePath) &&
179-
!mkdir($this->config->cachePath, self::DIR_PERMISSION, true) &&
180+
(
181+
!file_exists($this->config->cachePath) &&
182+
!mkdir($this->config->cachePath, self::DIR_PERMISSION, true)
183+
)
184+
||
180185
!is_dir($this->config->cachePath)
181186
) {
182187
throw new RuntimeException(sprintf('Directory "%s" was not created', $this->config->cachePath));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace ClassTransformer\Exceptions;
4+
5+
use LogicException;
6+
7+
/**
8+
* @infection-ignore-all
9+
*/
10+
class InstantiableClassException extends LogicException
11+
{
12+
/**
13+
* @param string $class
14+
*/
15+
public function __construct(string $class)
16+
{
17+
parent::__construct('Class ' . $class . ' is not instantiable.');
18+
}
19+
}

src/Reflection/RuntimeReflectionClass.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace ClassTransformer\Reflection;
66

7+
use ClassTransformer\Exceptions\InstantiableClassException;
78
use ReflectionClass;
89
use ReflectionException;
910
use InvalidArgumentException;
@@ -39,7 +40,7 @@ public function getProperties(): array
3940
$refInstance = new ReflectionClass($this->class);
4041

4142
if (!$refInstance->isInstantiable()) {
42-
throw new InvalidArgumentException('Class ' . $this->class . ' is not instantiable.');
43+
throw new InstantiableClassException($this->class);
4344
}
4445

4546
$properties = $refInstance->getProperties();

src/Reflection/Types/PropertyTypeFactory.php

+6-14
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,11 @@ public static function create(RuntimeReflectionProperty $property)
3535
$isNullable = $reflectionType->allowsNull();
3636
$isScalar = $reflectionType->isBuiltin();
3737
} else {
38-
$type = (string)$reflectionType;
38+
$type = $reflectionType;
3939
$isScalar = $reflectionType->isBuiltin();
4040
$isNullable = $reflectionType->allowsNull();
4141
}
4242

43-
if (($isScalar && $type !== TypeEnums::TYPE_ARRAY) || $property->notTransform()) {
44-
return new ScalarType(
45-
$type,
46-
$isScalar,
47-
$isNullable,
48-
);
49-
}
50-
5143
if ($type === TypeEnums::TYPE_ARRAY) {
5244
$arrayTypeAttr = $property->getAttributeArguments(ConvertArray::class);
5345

@@ -68,23 +60,23 @@ public static function create(RuntimeReflectionProperty $property)
6860
return $type;
6961
}
7062

71-
if (function_exists('enum_exists') && !$isScalar && enum_exists($type)) {
72-
return new EnumType(
63+
if ($isScalar || $property->notTransform()) {
64+
return new ScalarType(
7365
$type,
7466
$isScalar,
7567
$isNullable,
7668
);
7769
}
7870

79-
if (!$isScalar) {
80-
return new TransformableType(
71+
if (function_exists('enum_exists') && !$isScalar && enum_exists($type)) {
72+
return new EnumType(
8173
$type,
8274
$isScalar,
8375
$isNullable,
8476
);
8577
}
8678

87-
return new PropertyType(
79+
return new TransformableType(
8880
$type,
8981
$isScalar,
9082
$isNullable,

tests/Integration/ClassTransformerFromArrayTest.php

+26-8
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Tests\Integration;
66

7+
use ClassTransformer\Hydrator;
78
use ReflectionException;
89
use PHPUnit\Framework\TestCase;
910
use Tests\Integration\DTO\ConstructDto;
@@ -34,7 +35,9 @@ class ClassTransformerFromArrayTest extends TestCase
3435
public function testBaseArray(): void
3536
{
3637
$data = $this->getBaseArrayData();
37-
$userDTO = ClassTransformer::transform(UserDTO::class, $data);
38+
39+
$userDTO = Hydrator::init()->create(UserDTO::class, $data);
40+
3841
self::assertInstanceOf(UserDTO::class, $userDTO);
3942
self::assertEquals($data['id'], $userDTO->id);
4043
self::assertEquals($data['email'], $userDTO->email);
@@ -64,7 +67,7 @@ public function testBaseArray(): void
6467
public function testEmptyClass(): void
6568
{
6669
$data = $this->getBaseArrayData();
67-
$instance = ClassTransformer::transform(EmptyClassDto::class, $data);
70+
$instance = Hydrator::init()->create(EmptyClassDto::class, $data);
6871
self::assertInstanceOf(EmptyClassDto::class, $instance);
6972
}
7073

@@ -77,7 +80,7 @@ public function testScalarArray(): void
7780
'stringList' => [100, 200, 300],
7881
'intList' => [400, 500, 600]
7982
];
80-
$dto = ClassTransformer::transform(ArrayScalarDTO::class, $data);
83+
$dto = Hydrator::init()->create(ArrayScalarDTO::class, $data);
8184
self::assertInstanceOf(ArrayScalarDTO::class, $dto);
8285
self::assertIsString($dto->stringList[0]);
8386
self::assertEquals($dto->stringList[0], '100');
@@ -94,7 +97,9 @@ public function testNullArray(): void
9497
'id' => 1,
9598
'products' => null
9699
];
97-
$userDTO = ClassTransformer::transform(ArrayScalarDTO::class, $data);
100+
101+
$userDTO = Hydrator::init()->create(ArrayScalarDTO::class, $data);
102+
98103
self::assertInstanceOf(ArrayScalarDTO::class, $userDTO);
99104
}
100105

@@ -104,8 +109,11 @@ public function testNullArray(): void
104109
public function testTransformCollection(): void
105110
{
106111
$data = $this->getArrayUsers();
107-
112+
108113
$users = ClassTransformer::transformCollection(UserDTO::class, $data);
114+
self::assertCount(count($data), $users);
115+
116+
$users = Hydrator::init()->createCollection(UserDTO::class, $data);
109117

110118
self::assertCount(count($data), $users);
111119
foreach ($users as $key => $user) {
@@ -125,6 +133,11 @@ public function testTransformMultiple(): void
125133
$purchaseData = $this->getRecursiveArrayData();
126134

127135
$result = ClassTransformer::transformMultiple([UserDTO::class, PurchaseDTO::class], [$userData, $purchaseData]);
136+
[$user, $purchase] = $result;
137+
self::assertInstanceOf(UserDTO::class, $user);
138+
self::assertInstanceOf(PurchaseDTO::class, $purchase);
139+
140+
$result = Hydrator::init()->createMultiple([UserDTO::class, PurchaseDTO::class], [$userData, $purchaseData]);
128141

129142
[$user, $purchase] = $result;
130143

@@ -142,7 +155,8 @@ public function testTransformMultiple(): void
142155
public function testRecursiveArray(): void
143156
{
144157
$data = $this->getRecursiveArrayData();
145-
$purchaseDTO = ClassTransformer::transform(PurchaseDTO::class, $data);
158+
$purchaseDTO = Hydrator::init()->create(PurchaseDTO::class, $data);
159+
146160
self::assertInstanceOf(PurchaseDTO::class, $purchaseDTO);
147161
self::assertInstanceOf(UserDTO::class, $purchaseDTO->user);
148162
self::assertEquals($data['user']['id'], $purchaseDTO->user->id);
@@ -169,7 +183,9 @@ public function testRecursiveArray(): void
169183
public function testTripleRecursiveArray(): void
170184
{
171185
$data = $this->getTripleRecursiveArray();
172-
$basketDTO = ClassTransformer::transform(BasketDTO::class, $data);
186+
187+
$basketDTO = Hydrator::init()->create(BasketDTO::class, $data);
188+
173189
foreach ($basketDTO->orders as $key => $purchase) {
174190
self::assertInstanceOf(PurchaseDTO::class, $purchase);
175191
self::assertInstanceOf(UserDTO::class, $purchase->user);
@@ -197,7 +213,9 @@ public function testTripleRecursiveArray(): void
197213
public function testEmptyTypeObject(): void
198214
{
199215
$data = $this->getBaseArrayData();
200-
$userDTO = ClassTransformer::transform(UserEmptyTypeDTO::class, $data);
216+
217+
$userDTO = Hydrator::init()->create(UserEmptyTypeDTO::class, $data);
218+
201219
self::assertInstanceOf(UserEmptyTypeDTO::class, $userDTO);
202220
self::assertEquals($data['id'], $userDTO->id);
203221
self::assertEquals($data['email'], $userDTO->email);

tests/Units/CacheGeneratorTest.php

+14-8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Tests\Units;
44

5+
use ClassTransformer\Enums\TypeEnums;
56
use RuntimeException;
67
use Tests\ClearCache;
78
use Tests\Units\DTO\ColorEnum;
@@ -18,7 +19,7 @@ class CacheGeneratorTest extends TestCase
1819
use ClearCache;
1920

2021
private HydratorConfig $config;
21-
22+
2223
protected function setUp(): void
2324
{
2425
parent::setUp();
@@ -42,15 +43,13 @@ protected function setUp(): void
4243
/**
4344
* @throws \ReflectionException
4445
*/
45-
/*public function testGenerateException(): void
46+
public function testGenerateException(): void
4647
{
4748
$this->expectException(RuntimeException::class);
48-
$class = new ReflectionClass(CacheGenerator::class);
49-
$class->
50-
$method = $class->getMethod('makeCacheDir');
51-
$method->setAccessible(true);
52-
$method->invoke(new CacheGenerator(UserCacheableDTO::class),[]);
53-
}*/
49+
$dir = __DIR__ . '/CacheGeneratorTest.php';
50+
$generator = new CacheGenerator(UserCacheableDTO::class, new HydratorConfig(true, $dir));
51+
$dto = $generator->generate();
52+
}
5453

5554
public function testGenerateCache(): void
5655
{
@@ -79,6 +78,13 @@ public function testGenerateCache(): void
7978
$this->assertIsArray($property->attributes);
8079
$this->assertEmpty($property->attributes);
8180

81+
$property = $cache['properties'][2];
82+
83+
$this->assertEquals(UserCacheableDTO::class, $property->class);
84+
$this->assertEquals('phone', $property->name);
85+
$this->assertEquals(TypeEnums::TYPE_MIXED, $property->type->name);
86+
$this->assertCount(1, $property->aliases);
87+
8288
$property = $cache['properties'][5];
8389
$this->assertIsArray($property->attributes);
8490
$this->assertCount(1, $property->attributes);

tests/Units/DTO/AbstractClass.php

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Tests\Units\DTO;
4+
5+
/**
6+
* Class AbstractClass
7+
*
8+
* @author yzen.dev <yzen.dev@gmail.com>
9+
*/
10+
abstract class AbstractClass
11+
{
12+
13+
}

tests/Units/DTO/ExtendedDto.php

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
class ExtendedDto
1010
{
11+
public AbstractClass $mixed;
12+
1113
public int $id;
1214

1315
public ?string $email;
@@ -45,6 +47,8 @@ class ExtendedDto
4547

4648
/** @var array<mixed> */
4749
public array $mixedItems;
50+
51+
public UserDto $user;
4852

4953
public function setEmailAttribute($value)
5054
{

tests/Units/DTO/UserCacheableDTO.php

+3
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44

55
namespace Tests\Units\DTO;
66

7+
use ClassTransformer\Attributes\FieldAlias;
78
use ClassTransformer\Attributes\WritingStyle;
89

910
class UserCacheableDTO
1011
{
1112
public int $id;
1213
public ?string $email;
14+
15+
#[FieldAlias('contact')]
1316
public $phone;
1417

1518
/** @var array<int> $orders Order list */

0 commit comments

Comments
 (0)