Completed
Pull Request — master (#2)
by Tomasz
02:10
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\NormalizerContext\ParentNormalizerContext;
17
use Thunder\Serializard\Serializard;
18
use Thunder\Serializard\Tests\Fake\Context\FakeNormalizerContext;
19
use Thunder\Serializard\Tests\Fake\FakeArticle;
20
use Thunder\Serializard\Tests\Fake\FakeTag;
21
use Thunder\Serializard\Tests\Fake\FakeUser;
22
use Thunder\Serializard\Tests\Fake\FakeUserParent;
23
use Thunder\Serializard\Tests\Fake\FakeUserParentParent;
24
use Thunder\Serializard\Tests\Fake\Interfaces\TypeA;
25
use Thunder\Serializard\Tests\Fake\Interfaces\TypeB;
26
use Thunder\Serializard\Tests\Fake\Interfaces\TypeInterface;
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, 'type', 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, 'user', new ReflectionNormalizer());
104
        $normalizers->add($tagClass, 'tag', new ReflectionNormalizer());
105
106
        $hydrators = new FallbackHydratorContainer();
107
108
        $formats = new FormatContainer();
109
        $formats->add('xml', new XmlFormat());
110
        $formats->add('yaml', new YamlFormat());
111
        $formats->add('json', new JsonFormat());
112
        $formats->add('array', new ArrayFormat());
113
114
        $serializard = new Serializard($formats, $normalizers, $hydrators);
115
116
        $this->expectException('RuntimeException');
117
        $serializard->serialize($var, $format);
118
    }
119
120
    public function provideCycles()
121
    {
122
        $user = new FakeUser(1, 'Thomas', new FakeTag(100, 'various'));
123
        $user->addTag(new FakeTag(10, 'sth'));
124
        $user->addTag(new FakeTag(11, 'xyz'));
125
        $user->addTag(new FakeTag(12, 'rnd'));
126
127
        return array(
128
            array($user, 'xml'),
129
            array($user, 'json'),
130
            array($user, 'yaml'),
131
            array($user, 'array'),
132
        );
133
    }
134
135
    private function getSerializard()
136
    {
137
        $userClass = 'Thunder\Serializard\Tests\Fake\FakeUser';
138
        $tagClass = 'Thunder\Serializard\Tests\Fake\FakeTag';
139
140
        $normalizers = new FallbackNormalizerContainer();
141
        $normalizers->add($userClass, 'user', new ReflectionNormalizer());
142
        $normalizers->add($tagClass, 'tag', function(FakeTag $tag) {
143
            return array(
144
                'id' => $tag->getId(),
145
                'name' => $tag->getName(),
146
            );
147
        });
148
149
        $hydrators = new FallbackHydratorContainer();
150 View Code Duplication
        $hydrators->add($userClass, 'user', 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...
151
            $tagHandler = $handlers->getHandler($tagClass);
152
153
            $user = new FakeUser($data['id'], $data['name'], $tagHandler($data['tag'], $handlers));
154
            foreach($data['tags'] as $tag) {
155
                $user->addTag($tagHandler($tag, $handlers));
156
            }
157
158
            return $user;
159
        });
160
        $hydrators->add($tagClass, 'tag', 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...
161
            return new FakeTag($data['id'], $data['name']);
162
        });
163
164
        $formats = new FormatContainer();
165
        $formats->add('xml', new XmlFormat());
166
        $formats->add('yaml', new YamlFormat());
167
        $formats->add('json', new JsonFormat());
168
        $formats->add('array', new ArrayFormat());
169
170
        return new Serializard($formats, $normalizers, $hydrators);
171
    }
172
173
    public function testParent()
174
    {
175
        $userClass = 'Thunder\Serializard\Tests\Fake\FakeUser';
176
        $user = new FakeUser(1, '[email protected]', new FakeTag(1, 'tag'));
177
178
        $formats = new FormatContainer();
179
        $formats->add('array', new ArrayFormat());
180
        $normalizers = new FallbackNormalizerContainer();
181
        $hydrators = new FallbackHydratorContainer();
182
        $serializard = new Serializard($formats, $normalizers, $hydrators);
183
184
        $normalizers->add($userClass.'ParentParent', 'user', 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...
185
        $this->assertSame('ancestor', $serializard->serialize($user, 'array'));
186
187
        $normalizers->add($userClass.'Parent', 'user', 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...
188
        $this->assertSame('parent', $serializard->serialize($user, 'array'));
189
190
        $normalizers->add($userClass, 'user', 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...
191
        $this->assertSame('user', $serializard->serialize($user, 'array'));
192
    }
193
194
    public function testContext()
195
    {
196
        $userClass = 'Thunder\Serializard\Tests\Fake\FakeUser';
197
        $articleClass = 'Thunder\Serializard\Tests\Fake\FakeArticle';
198
        $tagClass = 'Thunder\Serializard\Tests\Fake\FakeTag';
199
200
        $formats = new FormatContainer();
201
        $formats->add('format', new ArrayFormat());
202
203
        $hydrators = new FallbackHydratorContainer();
204
        $normalizers = new FallbackNormalizerContainer();
205
        $normalizers->add($articleClass, 'article', function(FakeArticle $article) {
206
            return $article->getTag();
207
        });
208
        $normalizers->add($userClass, 'user', function(FakeUser $user) {
209
            return $user->getTag();
210
        });
211
        $normalizers->add($tagClass, 'tag', function(FakeTag $tag, NormalizerContextInterface $context) {
212
            return get_class($context->getParent());
213
        });
214
215
        $serializard = new Serializard($formats, $normalizers, $hydrators);
216
217
        $tag = new FakeTag(1, 'name');
218
        $user = new FakeUser(1, 'name', $tag);
219
        $article = new FakeArticle(1, 'title', $user, $tag);
220
221
        $this->assertSame($userClass, $serializard->serialize($user, 'format', new FakeNormalizerContext()));
222
        $context = new FakeNormalizerContext();
223
        $this->assertSame($articleClass, $serializard->serialize($article, 'format', $context));
224
        $this->assertSame(2, $context->getLevel());
225
    }
226
227
    public function testProcessWithCallbacks()
228
    {
229
        $userClass = 'Thunder\Serializard\Tests\Fake\FakeUser';
230
        $articleClass = 'Thunder\Serializard\Tests\Fake\FakeArticle';
231
        $tagClass = 'Thunder\Serializard\Tests\Fake\FakeTag';
232
233
        $formats = new FormatContainer();
234
        $formats->add('json', new JsonFormat());
235
236
        $hydrators = new FallbackHydratorContainer();
237
        $hydrators->add($articleClass, 'article', function(array $data, HydratorContainerInterface $hydrators) use($tagClass, $userClass) {
238
            $user = call_user_func($hydrators->getHandler($userClass), $data['user'], $hydrators);
239
            $tag = call_user_func($hydrators->getHandler($tagClass), $data['tag'], $hydrators);
240
241
            return new FakeArticle($data['id'], $data['title'], $user, $tag);
242
        });
243 View Code Duplication
        $hydrators->add($userClass, 'user', 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...
244
            $tag = call_user_func($hydrators->getHandler($tagClass), $data['tag'], $hydrators);
245
246
            $user = new FakeUser($data['id'], $data['name'], $tag);
247
            foreach($data['tags'] as $tagData) {
248
                $user->addTag(call_user_func($hydrators->getHandler($tagClass), $tagData, $hydrators));
249
            }
250
251
            return $user;
252
        });
253
        $hydrators->add($tagClass, 'tag', 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...
254
            return new FakeTag($data['id'], $data['name']);
255
        });
256
257
        $normalizers = new FallbackNormalizerContainer();
258
        $normalizers->add($articleClass, 'article', 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...
259
            return array(
260
                'id' => $article->getId(),
261
                'title' => $article->getTitle(),
262
                'user' => $article->getUser(),
263
                'tag' => $article->getTag(),
264
            );
265
        });
266
        $normalizers->add($userClass, 'user', 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...
267
            return array(
268
                'id' => $user->getId(),
269
                'name' => $user->getName(),
270
                'tag' => $user->getTag(),
271
                'tags' => $user->getTags(),
272
            );
273
        });
274
        $normalizers->add($tagClass, 'tag', 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...
275
            return array(
276
                'id' => $tag->getId(),
277
                'name' => $tag->getName(),
278
            );
279
        });
280
281
        $serializard = new Serializard($formats, $normalizers, $hydrators);
282
283
        $tag = new FakeTag(1, 'tag');
284
        $user = new FakeUser(1, 'user', $tag);
285
        $user->addTag(new FakeTag(1, 'tag'));
286
        $article = new FakeArticle(1, 'title', $user, $tag);
287
288
        $json = $serializard->serialize($article, 'json', new FakeNormalizerContext());
289
290
        $this->assertEquals($article, $serializard->unserialize($json, $articleClass, 'json'));
291
    }
292
293
    public function testProcessWithReflection()
294
    {
295
        $userClass = 'Thunder\Serializard\Tests\Fake\FakeUser';
296
        $articleClass = 'Thunder\Serializard\Tests\Fake\FakeArticle';
297
        $tagClass = 'Thunder\Serializard\Tests\Fake\FakeTag';
298
299
        $formats = new FormatContainer();
300
        $formats->add('json', new JsonFormat());
301
302
        $hydrators = new FallbackHydratorContainer();
303
        $hydrators->add($articleClass, 'article', new ReflectionHydrator($articleClass, array(
304
            'user' => $userClass,
305
            'tag' => $tagClass,
306
        )));
307
        $hydrators->add($userClass, 'user', new ReflectionHydrator($userClass, array(
308
            'tag' => $tagClass,
309
            'tags' => $tagClass.'[]',
310
        )));
311
        $hydrators->add($tagClass, 'tag', new ReflectionHydrator($tagClass, array()));
312
313
        $normalizers = new FallbackNormalizerContainer();
314
        $normalizers->add($articleClass, 'article', new ReflectionNormalizer());
315
        $normalizers->add($userClass, 'user', new ReflectionNormalizer());
316
        $normalizers->add($tagClass, 'tag', new ReflectionNormalizer(array('user')));
317
318
        $serializard = new Serializard($formats, $normalizers, $hydrators);
319
320
        $tag = new FakeTag(1, 'tag');
321
        $user = new FakeUser(1, 'user', $tag);
322
        $user->addTag(new FakeTag(1, 'tag'));
323
        $tags = $user->getTags();
324
        $tags[0]->clearUser();
325
        $article = new FakeArticle(1, 'title', $user, $tag);
326
327
        $json = $serializard->serialize($article, 'json', new FakeNormalizerContext());
328
329
        $this->assertEquals($article, $serializard->unserialize($json, $articleClass, 'json'));
330
    }
331
332
    public function testInvalidSerializationFormat()
333
    {
334
        $this->expectException('RuntimeException');
335
        $this->getSerializard()->serialize(new \stdClass(), 'invalid');
336
    }
337
338
    public function testInvalidUnserializationFormat()
339
    {
340
        $this->expectException('RuntimeException');
341
        $this->getSerializard()->unserialize(new \stdClass(), 'stdClass', 'invalid');
342
    }
343
344
    public function testMissingClassSerializationHandler()
345
    {
346
        $this->expectException('RuntimeException');
347
        $this->getSerializard()->serialize(new \stdClass(), 'json');
348
    }
349
}
350