Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php |
||
| 23 | final class GenericEntityRemoveControllerTest extends TestCase |
||
| 24 | { |
||
| 25 | |||
| 26 | private GenericEntityRemoveController $controller; |
||
|
|
|||
| 27 | |||
| 28 | private ControllerHelperInterface $controllerHelper; |
||
| 29 | |||
| 30 | public function setUp() |
||
| 31 | { |
||
| 32 | $this->controllerHelper = $this->createMock(ControllerHelperInterface::class); |
||
| 33 | |||
| 34 | $this->controller = new GenericEntityRemoveController($this->controllerHelper, [ |
||
| 35 | 'entity-class' => SampleEntity::class |
||
| 36 | ]); |
||
| 37 | } |
||
| 38 | |||
| 39 | /** |
||
| 40 | * @test |
||
| 41 | */ |
||
| 42 | public function shouldRejectMissingEntityClass() |
||
| 43 | { |
||
| 44 | $this->expectException(InvalidArgumentException::class); |
||
| 45 | |||
| 46 | new GenericEntityRemoveController($this->controllerHelper, []); |
||
| 47 | } |
||
| 48 | |||
| 49 | /** |
||
| 50 | * @test |
||
| 51 | */ |
||
| 52 | public function shouldThrowExceptionIfEntityNotFound() |
||
| 53 | { |
||
| 54 | $this->expectException(InvalidArgumentException::class); |
||
| 55 | |||
| 56 | $this->controller->removeEntity("some-id"); |
||
| 57 | } |
||
| 58 | |||
| 59 | /** |
||
| 60 | * @test |
||
| 61 | */ |
||
| 62 | public function shouldRemoveEntity() |
||
| 63 | { |
||
| 64 | $entity = new SampleEntity(); |
||
| 65 | |||
| 66 | $this->controllerHelper->expects($this->once())->method('findEntity')->with( |
||
| 67 | $this->equalTo(SampleEntity::class), |
||
| 68 | $this->equalTo('some-id') |
||
| 69 | )->willReturn($entity); |
||
| 70 | |||
| 71 | $this->controllerHelper->expects($this->once())->method('removeEntity')->with( |
||
| 72 | $this->identicalTo($entity) |
||
| 73 | ); |
||
| 74 | |||
| 75 | /** @var Response $response */ |
||
| 76 | $response = $this->controller->removeEntity("some-id"); |
||
| 77 | |||
| 78 | $this->assertEquals(200, $response->getStatusCode()); |
||
| 79 | $this->assertEquals('Entity removed!', $response->getContent()); |
||
| 80 | } |
||
| 81 | |||
| 82 | /** |
||
| 83 | * @test |
||
| 84 | */ |
||
| 85 | public function shouldCheckIfAccessIsGranted() |
||
| 86 | { |
||
| 87 | $this->expectException(AccessDeniedException::class); |
||
| 88 | |||
| 89 | $entity = new SampleEntity(); |
||
| 90 | |||
| 91 | $this->controllerHelper->expects($this->once())->method('findEntity')->with( |
||
| 92 | $this->equalTo(SampleEntity::class), |
||
| 93 | $this->equalTo("some-id") |
||
| 94 | )->willReturn($entity); |
||
| 95 | |||
| 96 | $this->controllerHelper->expects($this->once())->method('denyAccessUnlessGranted')->with( |
||
| 97 | $this->equalTo('some-attribute'), |
||
| 98 | $this->identicalTo($entity) |
||
| 99 | )->will($this->returnCallback( |
||
| 100 | function () { |
||
| 101 | throw new AccessDeniedException('Lorem ipsum!'); |
||
| 102 | } |
||
| 103 | )); |
||
| 104 | |||
| 105 | $controller = new GenericEntityRemoveController($this->controllerHelper, [ |
||
| 106 | 'entity-class' => SampleEntity::class, |
||
| 107 | 'authorization-attribute' => 'some-attribute', |
||
| 108 | ]); |
||
| 109 | |||
| 110 | $controller->removeEntity("some-id"); |
||
| 111 | } |
||
| 112 | |||
| 113 | /** |
||
| 114 | * @test |
||
| 115 | */ |
||
| 116 | public function shouldBeCallableByInvokingController() |
||
| 117 | { |
||
| 118 | $entity = new SampleEntity(); |
||
| 119 | |||
| 120 | $this->controllerHelper->expects($this->once())->method('findEntity')->with( |
||
| 121 | $this->equalTo(SampleEntity::class), |
||
| 122 | $this->equalTo('some-id') |
||
| 123 | )->willReturn($entity); |
||
| 124 | $this->controllerHelper->expects($this->once())->method('dispatchEvent')->with( |
||
| 125 | $this->equalTo("symfony_generics.entity_interaction"), |
||
| 126 | $this->equalTo(new EntityInteractionEvent( |
||
| 127 | SampleEntity::class, |
||
| 128 | 'some-id', |
||
| 129 | $entity, |
||
| 130 | "__destruct" |
||
| 131 | )) |
||
| 132 | ); |
||
| 133 | |||
| 134 | $this->controllerHelper->expects($this->once())->method('removeEntity')->with( |
||
| 135 | $this->identicalTo($entity) |
||
| 136 | ); |
||
| 137 | |||
| 138 | /** @var Request $request */ |
||
| 139 | $request = $this->createMock(Request::class); |
||
| 140 | $request->method("get")->willReturn('some-id'); |
||
| 141 | |||
| 142 | $this->controllerHelper->method('getCurrentRequest')->willReturn($request); |
||
| 143 | |||
| 144 | /** @var Response $actualResponse */ |
||
| 145 | $actualResponse = ($this->controller)(); |
||
| 146 | |||
| 147 | $this->assertEquals(200, $actualResponse->getStatusCode()); |
||
| 148 | $this->assertEquals('Entity removed!', $actualResponse->getContent()); |
||
| 149 | } |
||
| 150 | |||
| 151 | /** |
||
| 152 | * @test |
||
| 153 | */ |
||
| 154 | public function shouldRejectCallWithoutRequest() |
||
| 155 | { |
||
| 156 | $this->expectException(InvalidArgumentException::class); |
||
| 157 | |||
| 158 | $controller = new GenericEntityRemoveController($this->controllerHelper, [ |
||
| 159 | 'entity-class' => SampleEntity::class, |
||
| 160 | ]); |
||
| 161 | |||
| 162 | $this->controllerHelper->method('getCurrentRequest')->willReturn(null); |
||
| 163 | |||
| 164 | $controller(); |
||
| 165 | } |
||
| 166 | |||
| 167 | } |
||
| 168 |