1<?php 2 3namespace spec\Prophecy\Doubler; 4 5use PhpSpec\ObjectBehavior; 6use Prophecy\Doubler\ClassPatch\ClassPatchInterface; 7use Prophecy\Doubler\Generator\ClassCreator; 8use Prophecy\Doubler\Generator\ClassMirror; 9use Prophecy\Doubler\Generator\Node\ClassNode; 10use Prophecy\Doubler\NameGenerator; 11 12class DoublerSpec extends ObjectBehavior 13{ 14 function let(ClassMirror $mirror, ClassCreator $creator, NameGenerator $namer) 15 { 16 $this->beConstructedWith($mirror, $creator, $namer); 17 } 18 19 function it_does_not_have_patches_by_default() 20 { 21 $this->getClassPatches()->shouldHaveCount(0); 22 } 23 24 function its_registerClassPatch_adds_a_patch_to_the_doubler(ClassPatchInterface $patch) 25 { 26 $this->registerClassPatch($patch); 27 $this->getClassPatches()->shouldReturn(array($patch)); 28 } 29 30 function its_getClassPatches_sorts_patches_by_priority( 31 ClassPatchInterface $alt1, 32 ClassPatchInterface $alt2, 33 ClassPatchInterface $alt3, 34 ClassPatchInterface $alt4 35 ) { 36 $alt1->getPriority()->willReturn(2); 37 $alt2->getPriority()->willReturn(50); 38 $alt3->getPriority()->willReturn(10); 39 $alt4->getPriority()->willReturn(0); 40 41 $this->registerClassPatch($alt1); 42 $this->registerClassPatch($alt2); 43 $this->registerClassPatch($alt3); 44 $this->registerClassPatch($alt4); 45 46 $this->getClassPatches()->shouldReturn(array($alt2, $alt3, $alt1, $alt4)); 47 } 48 49 function its_double_mirrors_alterates_and_instantiates_provided_class( 50 $mirror, 51 $creator, 52 $namer, 53 ClassPatchInterface $alt1, 54 ClassPatchInterface $alt2, 55 \ReflectionClass $class, 56 \ReflectionClass $interface1, 57 \ReflectionClass $interface2, 58 ClassNode $node 59 ) { 60 $mirror->reflect($class, array($interface1, $interface2))->willReturn($node); 61 $alt1->supports($node)->willReturn(true); 62 $alt2->supports($node)->willReturn(false); 63 $alt1->getPriority()->willReturn(1); 64 $alt2->getPriority()->willReturn(2); 65 $namer->name($class, array($interface1, $interface2))->willReturn('SplStack'); 66 $class->getName()->willReturn('stdClass'); 67 $interface1->getName()->willReturn('ArrayAccess'); 68 $interface2->getName()->willReturn('Iterator'); 69 70 $alt1->apply($node)->shouldBeCalled(); 71 $alt2->apply($node)->shouldNotBeCalled(); 72 $creator->create('SplStack', $node)->shouldBeCalled(); 73 74 $this->registerClassPatch($alt1); 75 $this->registerClassPatch($alt2); 76 77 $this->double($class, array($interface1, $interface2)) 78 ->shouldReturnAnInstanceOf('SplStack'); 79 } 80 81 function it_double_instantiates_a_class_with_constructor_argument( 82 $mirror, 83 \ReflectionClass $class, 84 ClassNode $node, 85 $namer 86 ) { 87 $class->getName()->willReturn('ReflectionClass'); 88 $mirror->reflect($class, array())->willReturn($node); 89 $namer->name($class, array())->willReturn('ReflectionClass'); 90 91 $double = $this->double($class, array(), array('stdClass')); 92 $double->shouldBeAnInstanceOf('ReflectionClass'); 93 $double->getName()->shouldReturn('stdClass'); 94 } 95 96 function it_can_instantiate_class_with_final_constructor( 97 $mirror, 98 \ReflectionClass $class, 99 ClassNode $node, 100 $namer 101 ) { 102 $class->getName()->willReturn('spec\Prophecy\Doubler\WithFinalConstructor'); 103 $mirror->reflect($class, array())->willReturn($node); 104 $namer->name($class, array())->willReturn('spec\Prophecy\Doubler\WithFinalConstructor'); 105 106 $double = $this->double($class, array()); 107 108 $double->shouldBeAnInstanceOf('spec\Prophecy\Doubler\WithFinalConstructor'); 109 } 110} 111 112class WithFinalConstructor 113{ 114 final public function __construct() {} 115} 116