@@ -132,6 +132,76 @@ public function __invoke(ServerRequestInterface $request)
132132 $ this ->assertEquals ('{"num":1} ' , (string ) $ response ->getBody ());
133133 }
134134
135+ public function testCallableReturnsCallableForClassNameWithExplicitlyMappedSubclassForDependency ()
136+ {
137+ $ request = new ServerRequest ('GET ' , 'http://example.com/ ' );
138+
139+ $ dto = new class extends \stdClass { };
140+ $ dto ->name = 'Alice ' ;
141+
142+ $ controller = new class (new \stdClass ()) {
143+ private $ data ;
144+
145+ public function __construct (\stdClass $ data )
146+ {
147+ $ this ->data = $ data ;
148+ }
149+
150+ public function __invoke (ServerRequestInterface $ request )
151+ {
152+ return new Response (200 , [], json_encode ($ this ->data ));
153+ }
154+ };
155+
156+ $ container = new Container ([
157+ \stdClass::class => get_class ($ dto ),
158+ get_class ($ dto ) => $ dto
159+ ]);
160+
161+ $ callable = $ container ->callable (get_class ($ controller ));
162+ $ this ->assertInstanceOf (\Closure::class, $ callable );
163+
164+ $ response = $ callable ($ request );
165+ $ this ->assertInstanceOf (ResponseInterface::class, $ response );
166+ $ this ->assertEquals (200 , $ response ->getStatusCode ());
167+ $ this ->assertEquals ('{"name":"Alice"} ' , (string ) $ response ->getBody ());
168+ }
169+
170+ public function testCallableReturnsCallableForClassNameWithSubclassMappedFromFactoryForDependency ()
171+ {
172+ $ request = new ServerRequest ('GET ' , 'http://example.com/ ' );
173+
174+ $ dto = new class extends \stdClass { };
175+ $ dto ->name = 'Alice ' ;
176+
177+ $ controller = new class (new \stdClass ()) {
178+ private $ data ;
179+
180+ public function __construct (\stdClass $ data )
181+ {
182+ $ this ->data = $ data ;
183+ }
184+
185+ public function __invoke (ServerRequestInterface $ request )
186+ {
187+ return new Response (200 , [], json_encode ($ this ->data ));
188+ }
189+ };
190+
191+ $ container = new Container ([
192+ \stdClass::class => function () use ($ dto ) { return get_class ($ dto ); },
193+ get_class ($ dto ) => function () use ($ dto ) { return $ dto ; }
194+ ]);
195+
196+ $ callable = $ container ->callable (get_class ($ controller ));
197+ $ this ->assertInstanceOf (\Closure::class, $ callable );
198+
199+ $ response = $ callable ($ request );
200+ $ this ->assertInstanceOf (ResponseInterface::class, $ response );
201+ $ this ->assertEquals (200 , $ response ->getStatusCode ());
202+ $ this ->assertEquals ('{"name":"Alice"} ' , (string ) $ response ->getBody ());
203+ }
204+
135205 public function testCtorThrowsWhenMapContainsInvalidInteger ()
136206 {
137207 $ this ->expectException (\BadMethodCallException::class);
@@ -142,6 +212,21 @@ public function testCtorThrowsWhenMapContainsInvalidInteger()
142212 ]);
143213 }
144214
215+ public function testCallableReturnsCallableThatThrowsWhenFactoryReturnsInvalidClassName ()
216+ {
217+ $ request = new ServerRequest ('GET ' , 'http://example.com/ ' );
218+
219+ $ container = new Container ([
220+ \stdClass::class => function () { return 'invalid ' ; }
221+ ]);
222+
223+ $ callable = $ container ->callable (\stdClass::class);
224+
225+ $ this ->expectException (\BadMethodCallException::class);
226+ $ this ->expectExceptionMessage ('Class invalid not found ' );
227+ $ callable ($ request );
228+ }
229+
145230 public function testCallableReturnsCallableThatThrowsWhenFactoryReturnsInvalidInteger ()
146231 {
147232 $ request = new ServerRequest ('GET ' , 'http://example.com/ ' );
@@ -157,6 +242,21 @@ public function testCallableReturnsCallableThatThrowsWhenFactoryReturnsInvalidIn
157242 $ callable ($ request );
158243 }
159244
245+ public function testCallableReturnsCallableThatThrowsWhenFactoryIsRecursive ()
246+ {
247+ $ request = new ServerRequest ('GET ' , 'http://example.com/ ' );
248+
249+ $ container = new Container ([
250+ \stdClass::class => \stdClass::class
251+ ]);
252+
253+ $ callable = $ container ->callable (\stdClass::class);
254+
255+ $ this ->expectException (\BadMethodCallException::class);
256+ $ this ->expectExceptionMessage ('Factory for stdClass is recursive ' );
257+ $ callable ($ request );
258+ }
259+
160260 public function testInvokeContainerAsMiddlewareReturnsFromNextRequestHandler ()
161261 {
162262 $ request = new ServerRequest ('GET ' , 'http://example.com/ ' );
0 commit comments