1717use Doctrine \DBAL \Result ;
1818use Doctrine \ORM \EntityManagerInterface ;
1919use Doctrine \Persistence \ManagerRegistry ;
20- use PHPUnit \Framework \MockObject \MockObject ;
2120use Symfony \Bridge \Doctrine \Messenger \DoctrinePingConnectionMiddleware ;
2221use Symfony \Component \Messenger \Envelope ;
2322use Symfony \Component \Messenger \Exception \UnrecoverableMessageHandlingException ;
2625
2726class DoctrinePingConnectionMiddlewareTestextends MiddlewareTestCase
2827{
29- private Connection & MockObject $ connection ;
30- private EntityManagerInterface & MockObject $ entityManager ;
31- private ManagerRegistry & MockObject $ managerRegistry ;
28+ private Connection $ connection ;
29+ private EntityManagerInterface $ entityManager ;
30+ private ManagerRegistry $ managerRegistry ;
3231private DoctrinePingConnectionMiddleware $ middleware ;
3332private string $ entityManagerName ='default ' ;
3433
3534protected function setUp ():void
3635 {
37- $ this ->connection =$ this ->createMock (Connection::class);
36+ $ this ->connection =$ this ->createStub (Connection::class);
3837
39- $ this ->entityManager =$ this ->createMock (EntityManagerInterface::class);
38+ $ this ->entityManager =$ this ->createStub (EntityManagerInterface::class);
4039$ this ->entityManager ->method ('getConnection ' )->willReturn ($ this ->connection );
4140
42- $ this ->managerRegistry =$ this ->createMock (ManagerRegistry::class);
41+ $ this ->managerRegistry =$ this ->createStub (ManagerRegistry::class);
4342$ this ->managerRegistry ->method ('getManager ' )->willReturn ($ this ->entityManager );
4443
4544$ this ->middleware =new DoctrinePingConnectionMiddleware (
@@ -50,6 +49,14 @@ protected function setUp(): void
5049
5150public function testMiddlewarePingOk ()
5251 {
52+ $ this ->connection =$ this ->createMock (Connection::class);
53+ $ this ->entityManager =$ this ->createStub (EntityManagerInterface::class);
54+ $ this ->entityManager ->method ('getConnection ' )->willReturn ($ this ->connection );
55+ $ this ->managerRegistry =$ this ->createStub (ManagerRegistry::class);
56+ $ this ->managerRegistry ->method ('getManager ' )->willReturn ($ this ->entityManager );
57+
58+ $ middleware =new DoctrinePingConnectionMiddleware ($ this ->managerRegistry ,$ this ->entityManagerName );
59+
5360$ this ->connection ->method ('getDatabasePlatform ' )
5461 ->willReturn ($ this ->mockPlatform ());
5562
@@ -59,10 +66,10 @@ public function testMiddlewarePingOk()
5966static $ counter =0 ;
6067
6168if (1 === ++$ counter ) {
62- throw $ this ->createMock (DBALException::class);
69+ throw $ this ->createStub (DBALException::class);
6370 }
6471
65- return $ this ->createMock (Result::class);
72+ return $ this ->createStub (Result::class);
6673 });
6774
6875$ this ->connection ->expects ($ this ->once ())
@@ -72,13 +79,25 @@ public function testMiddlewarePingOk()
7279$ envelope =new Envelope (new \stdClass (), [
7380new ConsumedByWorkerStamp (),
7481 ]);
75- $ this -> middleware ->handle ($ envelope ,$ this ->getStackMock ());
82+ $ middleware ->handle ($ envelope ,$ this ->getStackMock ());
7683 }
7784
7885public function testMiddlewarePingResetEntityManager ()
7986 {
87+ $ this ->connection =$ this ->createStub (Connection::class);
88+ $ this ->entityManager =$ this ->createMock (EntityManagerInterface::class);
89+ $ this ->entityManager ->method ('getConnection ' )->willReturn ($ this ->connection );
90+ $ this ->managerRegistry =$ this ->createMock (ManagerRegistry::class);
91+ $ this ->managerRegistry ->method ('getManager ' )->willReturn ($ this ->entityManager );
92+
93+ $ middleware =new DoctrinePingConnectionMiddleware (
94+ $ this ->managerRegistry ,
95+ $ this ->entityManagerName
96+ );
97+
8098$ this ->connection ->method ('getDatabasePlatform ' )
8199 ->willReturn ($ this ->mockPlatform ());
100+ $ this ->connection ->method ('executeQuery ' )->willReturn ($ this ->createStub (Result::class));
82101
83102$ this ->entityManager ->expects ($ this ->once ())
84103 ->method ('isOpen ' )
@@ -92,15 +111,14 @@ public function testMiddlewarePingResetEntityManager()
92111$ envelope =new Envelope (new \stdClass (), [
93112new ConsumedByWorkerStamp (),
94113 ]);
95- $ this -> middleware ->handle ($ envelope ,$ this ->getStackMock ());
114+ $ middleware ->handle ($ envelope ,$ this ->getStackMock ());
96115 }
97116
98117public function testInvalidEntityManagerThrowsException ()
99118 {
100- $ managerRegistry =$ this ->createMock (ManagerRegistry::class);
119+ $ managerRegistry =$ this ->createStub (ManagerRegistry::class);
101120$ managerRegistry
102121 ->method ('getManager ' )
103- ->with ('unknown_manager ' )
104122 ->willThrowException (new \InvalidArgumentException ());
105123
106124$ middleware =new DoctrinePingConnectionMiddleware ($ managerRegistry ,'unknown_manager ' );
@@ -112,19 +130,112 @@ public function testInvalidEntityManagerThrowsException()
112130
113131public function testMiddlewareNoPingInNonWorkerContext ()
114132 {
133+ $ this ->connection =$ this ->createMock (Connection::class);
134+ $ this ->entityManager =$ this ->createStub (EntityManagerInterface::class);
135+ $ this ->entityManager ->method ('getConnection ' )->willReturn ($ this ->connection );
136+ $ this ->managerRegistry =$ this ->createStub (ManagerRegistry::class);
137+ $ this ->managerRegistry ->method ('getManager ' )->willReturn ($ this ->entityManager );
138+
139+ $ middleware =new DoctrinePingConnectionMiddleware (
140+ $ this ->managerRegistry ,
141+ $ this ->entityManagerName
142+ );
143+
115144$ this ->connection ->expects ($ this ->never ())
116145 ->method ('close ' )
117146 ;
118147
119148$ envelope =new Envelope (new \stdClass ());
120- $ this ->middleware ->handle ($ envelope ,$ this ->getStackMock ());
149+ $ middleware ->handle ($ envelope ,$ this ->getStackMock ());
150+ }
151+
152+ public function testMiddlewarePingsAllConnectionsWhenEntityManagerNameIsNull ()
153+ {
154+ $ firstConnection =$ this ->connectionExpectingOnePing ();
155+ $ secondConnection =$ this ->connectionExpectingOnePing ();
156+
157+ $ registry =$ this ->createRegistryForManagers ([
158+ 'first ' =>$ this ->createManagerWithConnection ($ firstConnection ),
159+ 'second ' =>$ this ->createManagerWithConnection ($ secondConnection ),
160+ ]);
161+
162+ $ middleware =new DoctrinePingConnectionMiddleware ($ registry );
163+
164+ $ envelope =new Envelope (new \stdClass (), [
165+ new ConsumedByWorkerStamp (),
166+ ]);
167+ $ middleware ->handle ($ envelope ,$ this ->getStackMock ());
168+ }
169+
170+ public function testMiddlewareResetsClosedManagersWhenEntityManagerNameIsNull ()
171+ {
172+ $ registry =$ this ->createRegistryForManagers ([
173+ 'open ' =>$ this ->createManagerWithConnection ($ this ->connectionExpectingOnePing (),true ),
174+ 'closed ' =>$ this ->createManagerWithConnection ($ this ->connectionExpectingOnePing (),false ),
175+ ],true );
176+ $ registry ->expects ($ this ->once ())
177+ ->method ('resetManager ' )
178+ ->with ('closed ' )
179+ ;
180+
181+ $ middleware =new DoctrinePingConnectionMiddleware ($ registry );
182+
183+ $ envelope =new Envelope (new \stdClass (), [
184+ new ConsumedByWorkerStamp (),
185+ ]);
186+ $ middleware ->handle ($ envelope ,$ this ->getStackMock ());
121187 }
122188
123- private function mockPlatform ():AbstractPlatform & MockObject
189+ private function mockPlatform ():AbstractPlatform
124190 {
125- $ platform =$ this ->createMock (AbstractPlatform::class);
191+ $ platform =$ this ->createStub (AbstractPlatform::class);
126192$ platform ->method ('getDummySelectSQL ' )->willReturn ('SELECT 1 ' );
127193
128194return $ platform ;
129195 }
196+
197+ private function connectionExpectingOnePing ():Connection
198+ {
199+ $ connection =$ this ->createMock (Connection::class);
200+ $ connection ->method ('getDatabasePlatform ' )->willReturn ($ this ->mockPlatform ());
201+ $ connection ->expects ($ this ->once ())->method ('executeQuery ' );
202+
203+ return $ connection ;
204+ }
205+
206+ private function createManagerWithConnection (Connection $ connection , ?bool $ isOpen =null ):EntityManagerInterface
207+ {
208+ $ manager =null ===$ isOpen ?$ this ->createStub (EntityManagerInterface::class) :$ this ->createMock (EntityManagerInterface::class);
209+ $ manager ->method ('getConnection ' )->willReturn ($ connection );
210+
211+ if (null !==$ isOpen ) {
212+ $ manager ->expects ($ this ->once ())->method ('isOpen ' )->willReturn ($ isOpen );
213+ }
214+
215+ return $ manager ;
216+ }
217+
218+ /**
219+ * @param array<string, EntityManagerInterface> $managers
220+ */
221+ private function createRegistryForManagers (array $ managers ,bool $ withExpectations =false ):ManagerRegistry
222+ {
223+ $ defaultName =array_key_first ($ managers );
224+
225+ $ registry =$ withExpectations ?$ this ->createMock (ManagerRegistry::class) :$ this ->createStub (ManagerRegistry::class);
226+
227+ if ($ withExpectations ) {
228+ $ registry ->expects ($ this ->any ())->method ('getManagerNames ' )->willReturn (array_combine (array_keys ($ managers ),array_keys ($ managers )));
229+ $ registry ->expects ($ this ->any ())->method ('getManager ' )->willReturnCallback (static function (?string $ name )use ($ managers ,$ defaultName ): ?EntityManagerInterface {
230+ return $ managers [$ name ??$ defaultName ] ??null ;
231+ });
232+ }else {
233+ $ registry ->method ('getManagerNames ' )->willReturn (array_combine (array_keys ($ managers ),array_keys ($ managers )));
234+ $ registry ->method ('getManager ' )->willReturnCallback (static function (?string $ name )use ($ managers ,$ defaultName ): ?EntityManagerInterface {
235+ return $ managers [$ name ??$ defaultName ] ??null ;
236+ });
237+ }
238+
239+ return $ registry ;
240+ }
130241}