Completed
Pull Request — master (#4)
by Tomasz
03:46 queued 01:50
created

SerializardTest::testProcessWithCallbacks()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 65
Code Lines 43

Duplication

Lines 10
Ratio 15.38 %

Importance

Changes 0
Metric Value
dl 10
loc 65
rs 9.3571
c 0
b 0
f 0
cc 2
eloc 43
nc 1
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace Thunder\Serializard\Tests;
3
4
use Thunder\Serializard\Format\ArrayFormat;
5
use Thunder\Serializard\Format\JsonFormat;
6
use Thunder\Serializard\Format\XmlFormat;
7
use Thunder\Serializard\Format\YamlFormat;
8
use Thunder\Serializard\FormatContainer\FormatContainer;
9
use Thunder\Serializard\Hydrator\ReflectionHydrator;
10
use Thunder\Serializard\HydratorContainer\FallbackHydratorContainer;
11
use Thunder\Serializard\HydratorContainer\HydratorContainerInterface as Hydrators;
12
use Thunder\Serializard\HydratorContainer\HydratorContainerInterface;
13
use Thunder\Serializard\Normalizer\ReflectionNormalizer;
14
use Thunder\Serializard\NormalizerContainer\FallbackNormalizerContainer;
15
use Thunder\Serializard\NormalizerContext\NormalizerContextInterface;
16
use Thunder\Serializard\Serializard;
17
use Thunder\Serializard\Tests\Fake\Context\FakeNormalizerContext;
18
use Thunder\Serializard\Tests\Fake\FakeArticle;
19
use Thunder\Serializard\Tests\Fake\FakeTag;
20
use Thunder\Serializard\Tests\Fake\FakeUser;
21
use Thunder\Serializard\Tests\Fake\FakeUserParent;
22
use Thunder\Serializard\Tests\Fake\FakeUserParentParent;
23
use Thunder\Serializard\Tests\Fake\Interfaces\TypeA;
24
use Thunder\Serializard\Tests\Fake\Interfaces\TypeB;
25
use Thunder\Serializard\Tests\Fake\Interfaces\TypeInterface;
26
use Thunder\Serializard\Utility\RootElementProviderUtility;
27
28
/**
29
 * @author Tomasz Kowalczyk <[email protected]>
30
 */
31
final class SerializardTest extends AbstractTestCase
32
{
33
    /** @dataProvider provideExamples */
34
    public function testSerializard($prefix, $factory)
35
    {
36
        $object = $factory();
37
38
        $serializard = $this->getSerializard();
39
40
        $file = __DIR__.'/examples/'.$prefix;
41
42
        $json = $serializard->serialize($object, 'json');
43
        $yaml = $serializard->serialize($object, 'yaml');
44
        $xml = $serializard->serialize($object, 'xml');
45
        $array = $serializard->serialize($object, 'array');
46
47
        $this->assertSame(file_get_contents($file.'.json'), $json."\n");
48
        $this->assertSame(file_get_contents($file.'.yaml'), $yaml);
49
        $this->assertSame(file_get_contents($file.'.xml'), $xml);
50
        $this->assertSame(require $file.'.php', $array);
51
52
        $userClass = 'Thunder\Serializard\Tests\Fake\FakeUser';
53
54
        $this->assertSame($json, $serializard->serialize($serializard->unserialize($json, $userClass, 'json'), 'json'));
55
        $this->assertSame($yaml, $serializard->serialize($serializard->unserialize($yaml, $userClass, 'yaml'), 'yaml'));
56
        $this->assertSame($xml, $serializard->serialize($serializard->unserialize($xml, $userClass, 'xml'), 'xml'));
57
        $this->assertSame($array, $serializard->serialize($serializard->unserialize($array, $userClass, 'array'), 'array'));
58
    }
59
60
    public function provideExamples()
61
    {
62
        return array(
63
            array('simple', function() {
64
                $user = new FakeUser(1, 'Thomas', new FakeTag(100, 'various'));
65
                $user->addTag(new FakeTag(10, 'sth'));
66
                $user->addTag(new FakeTag(11, 'xyz'));
67
                $user->addTag(new FakeTag(12, 'rnd'));
68
69
                return $user;
70
            }),
71
        );
72
    }
73
74
    public function testInterfaces()
75
    {
76
        $interface = 'Thunder\Serializard\Tests\Fake\Interfaces\TypeInterface';
77
        $normalizers = new FallbackNormalizerContainer();
78
        $normalizers->add($interface, function(TypeInterface $type) {
79
            return array(
80
                'type' => $type->getType(),
81
                'value' => $type->getValue(),
82
            );
83
        });
84
85
        $hydrators = new FallbackHydratorContainer();
86
87
        $formats = new FormatContainer();
88
        $formats->add('array', new ArrayFormat());
89
90
        $serializard = new Serializard($formats, $normalizers, $hydrators);
91
92
        $this->assertSame(array('type' => 'typeA', 'value' => 'valueA'), $serializard->serialize(new TypeA(), 'array'));
93
        $this->assertSame(array('type' => 'typeB', 'value' => 'valueB'), $serializard->serialize(new TypeB(), 'array'));
94
    }
95
96
    /** @dataProvider provideCycles */
97
    public function testCycleException($var, $format)
98
    {
99
        $userClass = 'Thunder\Serializard\Tests\Fake\FakeUser';
100
        $tagClass = 'Thunder\Serializard\Tests\Fake\FakeTag';
101
102
        $normalizers = new FallbackNormalizerContainer();
103
        $normalizers->add($userClass, new ReflectionNormalizer());
104
        $normalizers->add($tagClass, new ReflectionNormalizer());
105
106
        $hydrators = new FallbackHydratorContainer();
107
108
        $formats = new FormatContainer();
109
        $formats->add('xml', new XmlFormat(new RootElementProviderUtility([
110
            FakeUser::class => 'user',
111
            FakeTag::class => 'tag',
112
        ])));
113
        $formats->add('yaml', new YamlFormat());
114
        $formats->add('json', new JsonFormat());
115
        $formats->add('array', new ArrayFormat());
116
117
        $serializard = new Serializard($formats, $normalizers, $hydrators);
118
119
        $this->expectException('RuntimeException');
120
        $this->expectExceptionMessage('cycle');
121
        $serializard->serialize($var, $format);
122
    }
123
124
    public function provideCycles()
125
    {
126
        $user = new FakeUser(1, 'Thomas', new FakeTag(100, 'various'));
127
        $user->addTag(new FakeTag(10, 'sth'));
128
        $user->addTag(new FakeTag(11, 'xyz'));
129
        $user->addTag(new FakeTag(12, 'rnd'));
130
131
        return array(
132
            array($user, 'xml'),
133
            array($user, 'json'),
134
            array($user, 'yaml'),
135
            array($user, 'array'),
136
        );
137
    }
138
139
    private function getSerializard()
140
    {
141
        $userClass = 'Thunder\Serializard\Tests\Fake\FakeUser';
142
        $tagClass = 'Thunder\Serializard\Tests\Fake\FakeTag';
143
144
        $normalizers = new FallbackNormalizerContainer();
145
        $normalizers->add($userClass, new ReflectionNormalizer());
146
        $normalizers->add($tagClass, function(FakeTag $tag) {
147
            return array(
148
                'id' => $tag->getId(),
149
                'name' => $tag->getName(),
150
            );
151
        });
152
153
        $hydrators = new FallbackHydratorContainer();
154 View Code Duplication
        $hydrators->add($userClass, function(array $data, Hydrators $handlers) use($tagClass) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
155
            $tagHandler = $handlers->getHandler($tagClass);
156
157
            $user = new FakeUser($data['id'], $data['name'], $tagHandler($data['tag'], $handlers));
158
            foreach($data['tags'] as $tag) {
159
                $user->addTag($tagHandler($tag, $handlers));
160
            }
161
162
            return $user;
163
        });
164
        $hydrators->add($tagClass, function(array $data, Hydrators $handlers) {
0 ignored issues
show
Unused Code introduced by
The parameter $handlers is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
165
            return new FakeTag($data['id'], $data['name']);
166
        });
167
168
        $formats = new FormatContainer();
169
        $formats->add('xml', new XmlFormat(new RootElementProviderUtility([
170
            FakeUser::class => 'user',
171
            FakeTag::class => 'tag',
172
        ])));
173
        $formats->add('yaml', new YamlFormat());
174
        $formats->add('json', new JsonFormat());
175
        $formats->add('array', new ArrayFormat());
176
177
        return new Serializard($formats, $normalizers, $hydrators);
178
    }
179
180
    public function testParent()
181
    {
182
        $userClass = 'Thunder\Serializard\Tests\Fake\FakeUser';
183
        $user = new FakeUser(1, '[email protected]', new FakeTag(1, 'tag'));
184
185
        $formats = new FormatContainer();
186
        $formats->add('array', new ArrayFormat());
187
        $normalizers = new FallbackNormalizerContainer();
188
        $hydrators = new FallbackHydratorContainer();
189
        $serializard = new Serializard($formats, $normalizers, $hydrators);
190
191
        $normalizers->add($userClass.'ParentParent', function(FakeUserParentParent $user) { return 'ancestor'; });
0 ignored issues
show
Unused Code introduced by
The parameter $user is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
192
        $this->assertSame('ancestor', $serializard->serialize($user, 'array'));
193
194
        $normalizers->add($userClass.'Parent', function(FakeUserParent $user) { return 'parent'; });
0 ignored issues
show
Unused Code introduced by
The parameter $user is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
195
        $this->assertSame('parent', $serializard->serialize($user, 'array'));
196
197
        $normalizers->add($userClass, function(FakeUser $user) { return 'user'; });
0 ignored issues
show
Unused Code introduced by
The parameter $user is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
198
        $this->assertSame('user', $serializard->serialize($user, 'array'));
199
    }
200
201
    public function testContext()
202
    {
203
        $userClass = 'Thunder\Serializard\Tests\Fake\FakeUser';
204
        $articleClass = 'Thunder\Serializard\Tests\Fake\FakeArticle';
205
        $tagClass = 'Thunder\Serializard\Tests\Fake\FakeTag';
206
207
        $formats = new FormatContainer();
208
        $formats->add('format', new ArrayFormat());
209
210
        $hydrators = new FallbackHydratorContainer();
211
        $normalizers = new FallbackNormalizerContainer();
212
        $normalizers->add($articleClass, function(FakeArticle $article) {
213
            return $article->getTag();
214
        });
215
        $normalizers->add($userClass, function(FakeUser $user) {
216
            return $user->getTag();
217
        });
218
        $normalizers->add($tagClass, function(FakeTag $tag, NormalizerContextInterface $context) {
219
            return get_class($context->getParent());
220
        });
221
222
        $serializard = new Serializard($formats, $normalizers, $hydrators);
223
224
        $tag = new FakeTag(1, 'name');
225
        $user = new FakeUser(1, 'name', $tag);
226
        $article = new FakeArticle(1, 'title', $user, $tag);
227
228
        $this->assertSame($userClass, $serializard->serialize($user, 'format', new FakeNormalizerContext()));
229
        $context = new FakeNormalizerContext();
230
        $this->assertSame($articleClass, $serializard->serialize($article, 'format', $context));
231
        $this->assertSame(2, $context->getLevel());
232
    }
233
234
    public function testProcessWithCallbacks()
235
    {
236
        $userClass = 'Thunder\Serializard\Tests\Fake\FakeUser';
237
        $articleClass = 'Thunder\Serializard\Tests\Fake\FakeArticle';
238
        $tagClass = 'Thunder\Serializard\Tests\Fake\FakeTag';
239
240
        $formats = new FormatContainer();
241
        $formats->add('json', new JsonFormat());
242
243
        $hydrators = new FallbackHydratorContainer();
244
        $hydrators->add($articleClass, function(array $data, HydratorContainerInterface $hydrators) use($tagClass, $userClass) {
245
            $user = call_user_func($hydrators->getHandler($userClass), $data['user'], $hydrators);
246
            $tag = call_user_func($hydrators->getHandler($tagClass), $data['tag'], $hydrators);
247
248
            return new FakeArticle($data['id'], $data['title'], $user, $tag);
249
        });
250 View Code Duplication
        $hydrators->add($userClass, function(array $data, HydratorContainerInterface $hydrators) use($tagClass) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
251
            $tag = call_user_func($hydrators->getHandler($tagClass), $data['tag'], $hydrators);
252
253
            $user = new FakeUser($data['id'], $data['name'], $tag);
254
            foreach($data['tags'] as $tagData) {
255
                $user->addTag(call_user_func($hydrators->getHandler($tagClass), $tagData, $hydrators));
256
            }
257
258
            return $user;
259
        });
260
        $hydrators->add($tagClass, function(array $data, HydratorContainerInterface $hydrators) {
0 ignored issues
show
Unused Code introduced by
The parameter $hydrators is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
261
            return new FakeTag($data['id'], $data['name']);
262
        });
263
264
        $normalizers = new FallbackNormalizerContainer();
265
        $normalizers->add($articleClass, function(FakeArticle $article, NormalizerContextInterface $context) {
0 ignored issues
show
Unused Code introduced by
The parameter $context is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
266
            return array(
267
                'id' => $article->getId(),
268
                'title' => $article->getTitle(),
269
                'user' => $article->getUser(),
270
                'tag' => $article->getTag(),
271
            );
272
        });
273
        $normalizers->add($userClass, function(FakeUser $user, NormalizerContextInterface $context) {
0 ignored issues
show
Unused Code introduced by
The parameter $context is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
274
            return array(
275
                'id' => $user->getId(),
276
                'name' => $user->getName(),
277
                'tag' => $user->getTag(),
278
                'tags' => $user->getTags(),
279
            );
280
        });
281
        $normalizers->add($tagClass, function(FakeTag $tag, NormalizerContextInterface $context) {
0 ignored issues
show
Unused Code introduced by
The parameter $context is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
282
            return array(
283
                'id' => $tag->getId(),
284
                'name' => $tag->getName(),
285
            );
286
        });
287
288
        $serializard = new Serializard($formats, $normalizers, $hydrators);
289
290
        $tag = new FakeTag(1, 'tag');
291
        $user = new FakeUser(1, 'user', $tag);
292
        $user->addTag(new FakeTag(1, 'tag'));
293
        $article = new FakeArticle(1, 'title', $user, $tag);
294
295
        $json = $serializard->serialize($article, 'json', new FakeNormalizerContext());
296
297
        $this->assertEquals($article, $serializard->unserialize($json, $articleClass, 'json'));
298
    }
299
300
    public function testProcessWithReflection()
301
    {
302
        $userClass = 'Thunder\Serializard\Tests\Fake\FakeUser';
303
        $articleClass = 'Thunder\Serializard\Tests\Fake\FakeArticle';
304
        $tagClass = 'Thunder\Serializard\Tests\Fake\FakeTag';
305
306
        $formats = new FormatContainer();
307
        $formats->add('json', new JsonFormat());
308
309
        $hydrators = new FallbackHydratorContainer();
310
        $hydrators->add($articleClass, new ReflectionHydrator($articleClass, array(
311
            'user' => $userClass,
312
            'tag' => $tagClass,
313
        )));
314
        $hydrators->add($userClass, new ReflectionHydrator($userClass, array(
315
            'tag' => $tagClass,
316
            'tags' => $tagClass.'[]',
317
        )));
318
        $hydrators->add($tagClass, new ReflectionHydrator($tagClass, array()));
319
320
        $normalizers = new FallbackNormalizerContainer();
321
        $normalizers->add($articleClass, new ReflectionNormalizer());
322
        $normalizers->add($userClass, new ReflectionNormalizer());
323
        $normalizers->add($tagClass, new ReflectionNormalizer(array('user')));
324
325
        $serializard = new Serializard($formats, $normalizers, $hydrators);
326
327
        $tag = new FakeTag(1, 'tag');
328
        $user = new FakeUser(1, 'user', $tag);
329
        $user->addTag(new FakeTag(1, 'tag'));
330
        $tags = $user->getTags();
331
        $tags[0]->clearUser();
332
        $article = new FakeArticle(1, 'title', $user, $tag);
333
334
        $json = $serializard->serialize($article, 'json', new FakeNormalizerContext());
335
336
        $this->assertEquals($article, $serializard->unserialize($json, $articleClass, 'json'));
337
    }
338
339
    public function testInvalidSerializationFormat()
340
    {
341
        $this->expectException('RuntimeException');
342
        $this->getSerializard()->serialize(new \stdClass(), 'invalid');
343
    }
344
345
    public function testInvalidUnserializationFormat()
346
    {
347
        $this->expectException('RuntimeException');
348
        $this->getSerializard()->unserialize(new \stdClass(), 'stdClass', 'invalid');
349
    }
350
351
    public function testMissingClassSerializationHandler()
352
    {
353
        $this->expectException('RuntimeException');
354
        $this->getSerializard()->serialize(new \stdClass(), 'json');
355
    }
356
}
357