1414use Prophecy \Prophecy \ObjectProphecy ;
1515use Symfony \Component \HttpFoundation \JsonResponse ;
1616use Symfony \Component \HttpFoundation \Request ;
17- use Symfony \Component \HttpFoundation \ Response ;
18- use Symfony \Component \HttpKernel \Event \ GetResponseForExceptionEvent ;
17+ use Symfony \Component \HttpKernel \ Event \ ExceptionEvent ;
18+ use Symfony \Component \HttpKernel \HttpKernelInterface ;
1919
2020/** @covers \Phpro\ApiProblemBundle\EventListener\JsonApiProblemExceptionListener */
2121class JsonApiProblemExceptionListenerTest extends TestCase
@@ -26,10 +26,15 @@ class JsonApiProblemExceptionListenerTest extends TestCase
2626 private $ request ;
2727
2828 /**
29- * @var GetResponseForExceptionEvent|ObjectProphecy
29+ * @var ExceptionEvent
3030 */
3131 private $ event ;
3232
33+ /**
34+ * @var \Throwable
35+ */
36+ private $ exception ;
37+
3338 /**
3439 * @var ExceptionTransformerInterface|ObjectProphecy
3540 */
@@ -38,9 +43,14 @@ class JsonApiProblemExceptionListenerTest extends TestCase
3843 protected function setUp (): void
3944 {
4045 $ this ->request = $ this ->prophesize (Request::class);
41- $ this ->event = $ this ->prophesize (GetResponseForExceptionEvent::class);
42- $ this ->event ->getRequest ()->willReturn ($ this ->request );
43- $ this ->event ->getException ()->willReturn (new \Exception ('error ' ));
46+ $ httpKernel = $ this ->prophesize (HttpKernelInterface::class);
47+ $ this ->exception = new \Exception ('error ' );
48+ $ this ->event = new ExceptionEvent (
49+ $ httpKernel ->reveal (),
50+ $ this ->request ->reveal (),
51+ HttpKernelInterface::MASTER_REQUEST ,
52+ $ this ->exception
53+ );
4454 $ this ->exceptionTransformer = $ this ->prophesize (ExceptionTransformerInterface::class);
4555 $ this ->exceptionTransformer ->accepts (Argument::any ())->willReturn (false );
4656 }
@@ -51,10 +61,9 @@ public function it_does_nothing_on_non_json_requests(): void
5161 $ listener = new JsonApiProblemExceptionListener ($ this ->exceptionTransformer ->reveal (), false );
5262 $ this ->request ->getRequestFormat ()->willReturn ('html ' );
5363 $ this ->request ->getContentType ()->willReturn ('text/html ' );
64+ $ listener ->onKernelException ($ this ->event );
5465
55- $ this ->event ->setResponse (Argument::any ())->shouldNotBeCalled ();
56-
57- $ listener ->onKernelException ($ this ->event ->reveal ());
66+ $ this ->assertNull ($ this ->event ->getResponse ());
5867 }
5968
6069 /** @test */
@@ -63,10 +72,9 @@ public function it_runs_on_json_route_formats(): void
6372 $ listener = new JsonApiProblemExceptionListener ($ this ->exceptionTransformer ->reveal (), false );
6473 $ this ->request ->getRequestFormat ()->willReturn ('json ' );
6574 $ this ->request ->getContentType ()->willReturn (null );
75+ $ listener ->onKernelException ($ this ->event );
6676
67- $ this ->event ->setResponse (Argument::type (JsonResponse::class))->shouldBeCalled ();
68-
69- $ listener ->onKernelException ($ this ->event ->reveal ());
77+ $ this ->assertApiProblemWithResponseBody (500 , $ this ->parseDataForException ());
7078 }
7179
7280 /** @test */
@@ -76,9 +84,8 @@ public function it_runs_on_json_content_types(): void
7684 $ this ->request ->getRequestFormat ()->willReturn ('html ' );
7785 $ this ->request ->getContentType ()->willReturn ('application/json ' );
7886
79- $ this ->event ->setResponse (Argument::type (JsonResponse::class))->shouldBeCalled ();
80-
81- $ listener ->onKernelException ($ this ->event ->reveal ());
87+ $ listener ->onKernelException ($ this ->event );
88+ $ this ->assertApiProblemWithResponseBody (500 , $ this ->parseDataForException ());
8289 }
8390
8491 /** @test */
@@ -88,18 +95,8 @@ public function it_parses_an_api_problem_response(): void
8895 $ this ->request ->getRequestFormat ()->willReturn ('json ' );
8996 $ this ->request ->getContentType ()->willReturn ('application/json ' );
9097
91- $ this ->event ->setResponse (Argument::that (function (JsonResponse $ response ) {
92- return 500 === $ response ->getStatusCode ()
93- && 'application/problem+json ' === $ response ->headers ->get ('Content-Type ' )
94- && $ response ->getContent () === json_encode ([
95- 'status ' => 500 ,
96- 'type ' => HttpApiProblem::TYPE_HTTP_RFC ,
97- 'title ' => HttpApiProblem::getTitleForStatusCode (500 ),
98- 'detail ' => 'error ' ,
99- ]);
100- }))->shouldBeCalled ();
101-
102- $ listener ->onKernelException ($ this ->event ->reveal ());
98+ $ listener ->onKernelException ($ this ->event );
99+ $ this ->assertApiProblemWithResponseBody (500 , $ this ->parseDataForException ());
103100 }
104101
105102 /** @test */
@@ -115,13 +112,25 @@ public function it_uses_an_exception_transformer(): void
115112 $ this ->exceptionTransformer ->accepts (Argument::type (\Exception::class))->willReturn (true );
116113 $ this ->exceptionTransformer ->transform (Argument::type (\Exception::class))->willReturn ($ apiProblem ->reveal ());
117114
118- $ this ->event ->setResponse (Argument::that (function (JsonResponse $ response ) {
119- return Response::HTTP_BAD_REQUEST === $ response ->getStatusCode ()
120- && 'application/problem+json ' === $ response ->headers ->get ('Content-Type ' )
121- && $ response ->getContent () === json_encode ([]);
122- }))->shouldBeCalled ();
115+ $ listener ->onKernelException ($ this ->event );
116+ $ this ->assertApiProblemWithResponseBody (400 , []);
117+ }
123118
124- $ listener ->onKernelException ($ this ->event ->reveal ());
119+ /** @test */
120+ public function it_returns_the_status_code_from_the_api_problem (): void
121+ {
122+ $ listener = new JsonApiProblemExceptionListener ($ this ->exceptionTransformer ->reveal (), false );
123+ $ this ->request ->getRequestFormat ()->willReturn ('json ' );
124+ $ this ->request ->getContentType ()->willReturn ('application/json ' );
125+
126+ $ apiProblem = $ this ->prophesize (ApiProblemInterface::class);
127+ $ apiProblem ->toArray ()->willReturn (['status ' => 123 ]);
128+
129+ $ this ->exceptionTransformer ->accepts (Argument::type (\Exception::class))->willReturn (true );
130+ $ this ->exceptionTransformer ->transform (Argument::type (\Exception::class))->willReturn ($ apiProblem ->reveal ());
131+
132+ $ listener ->onKernelException ($ this ->event );
133+ $ this ->assertApiProblemWithResponseBody (123 , ['status ' => 123 ]);
125134 }
126135
127136 /** @test */
@@ -133,21 +142,36 @@ public function it_parses_a_debuggable_api_problem_response(): void
133142 $ data = ['status ' => 500 , 'detail ' => 'detail ' , 'debug ' => true ];
134143 $ apiProblem ->toDebuggableArray ()->willReturn ($ data );
135144 $ apiProblem ->toArray ()->willReturn ($ data );
136- $ exception = new \RuntimeException ();
137145
138- $ this ->event ->getException ()->willReturn ($ exception );
139- $ this ->exceptionTransformer ->accepts ($ exception )->willReturn (true );
140- $ this ->exceptionTransformer ->transform ($ exception )->willReturn ($ apiProblem ->reveal ());
146+ $ this ->exceptionTransformer ->accepts ($ this ->exception )->willReturn (true );
147+ $ this ->exceptionTransformer ->transform ($ this ->exception )->willReturn ($ apiProblem ->reveal ());
141148
142149 $ this ->request ->getRequestFormat ()->willReturn ('json ' );
143150 $ this ->request ->getContentType ()->willReturn ('application/json ' );
144151
145- $ this ->event ->setResponse (Argument::that (function (JsonResponse $ response ) use ($ data ) {
146- return 500 === $ response ->getStatusCode ()
147- && 'application/problem+json ' === $ response ->headers ->get ('Content-Type ' )
148- && $ response ->getContent () === json_encode ($ data );
149- }))->shouldBeCalled ();
152+ $ listener ->onKernelException ($ this ->event );
153+ $ this ->assertApiProblemWithResponseBody (500 , $ data );
154+ }
150155
151- $ listener ->onKernelException ($ this ->event ->reveal ());
156+ private function assertApiProblemWithResponseBody (int $ expectedResponseCode , array $ expectedData ): void
157+ {
158+ $ response = $ this ->event ->getResponse ();
159+ $ this ->assertInstanceOf (JsonResponse::class, $ response );
160+ $ this ->assertSame ($ expectedResponseCode , $ response ->getStatusCode ());
161+ $ this ->assertSame ('application/problem+json ' , $ response ->headers ->get ('Content-Type ' ));
162+ $ this ->assertJsonStringEqualsJsonString (
163+ \json_encode ($ expectedData ),
164+ $ this ->event ->getResponse ()->getContent ()
165+ );
166+ }
167+
168+ private function parseDataForException (): array
169+ {
170+ return [
171+ 'status ' => 500 ,
172+ 'type ' => HttpApiProblem::TYPE_HTTP_RFC ,
173+ 'title ' => HttpApiProblem::getTitleForStatusCode (500 ),
174+ 'detail ' => $ this ->exception ->getMessage (),
175+ ];
152176 }
153177}
0 commit comments