44use Jenssegers \Mongodb \Connection ;
55use Jenssegers \Mongodb \Eloquent \Model ;
66use MongoDB \BSON \ObjectId ;
7+ use MongoDB \Driver \Exception \BulkWriteException ;
78use MongoDB \Driver \Server ;
89
910class TransactionTest extends TestCase
@@ -317,6 +318,8 @@ public function testTransaction(): void
317318 {
318319 User::create (['name ' => 'klinson ' , 'age ' => 20 , 'title ' => 'admin ' ]);
319320
321+ // The $connection parameter may be unused, but is implicitly used to
322+ // test that the closure is executed with the connection as an argument.
320323 DB ::transaction (function (Connection $ connection ): void {
321324 User::create (['name ' => 'alcaeus ' , 'age ' => 38 , 'title ' => 'admin ' ]);
322325 User::where (['name ' => 'klinson ' ])->update (['age ' => 21 ]);
@@ -336,14 +339,18 @@ public function testTransactionRepeatsOnTransientFailure(): void
336339 $ timesRun = 0 ;
337340
338341 DB ::transaction (function () use (&$ timesRun ): void {
339- User::where (['name ' => 'klinson ' ])->update (['age ' => 21 ]);
342+ $ timesRun ++;
343+
344+ // Run a query to start the transaction on the server
345+ User::create (['name ' => 'alcaeus ' , 'age ' => 38 , 'title ' => 'admin ' ]);
340346
341- // Update user during transaction to simulate a simultaneous update
342- if ($ timesRun == 0 ) {
347+ // Update user outside of the session
348+ if ($ timesRun == 1 ) {
343349 DB ::getCollection ('users ' )->updateOne (['name ' => 'klinson ' ], ['$set ' => ['age ' => 22 ]]);
344350 }
345351
346- $ timesRun ++;
352+ // This update will create a write conflict, aborting the transaction
353+ User::where (['name ' => 'klinson ' ])->update (['age ' => 21 ]);
347354 }, 2 );
348355
349356 $ this ->assertSame (2 , $ timesRun );
@@ -356,14 +363,25 @@ public function testTransactionRespectsRepetitionLimit(): void
356363
357364 $ timesRun = 0 ;
358365
359- DB ::transaction (function () use (&$ timesRun ): void {
360- User::where (['name ' => 'klinson ' ])->update (['age ' => 21 ]);
366+ try {
367+ DB ::transaction (function () use (&$ timesRun ): void {
368+ $ timesRun ++;
361369
362- // Update user during transaction to simulate a simultaneous update
363- DB :: getCollection ( ' users ' )-> updateOne ( ['name ' => 'klinson ' ], [ ' $inc ' => [ ' age ' => 2 ] ]);
370+ // Run a query to start the transaction on the server
371+ User:: create ( ['name ' => 'alcaeus ' , ' age ' => 38 , ' title ' => ' admin ' ]);
364372
365- $ timesRun ++;
366- }, 2 );
373+ // Update user outside of the session
374+ DB ::getCollection ('users ' )->updateOne (['name ' => 'klinson ' ], ['$inc ' => ['age ' => 2 ]]);
375+
376+ // This update will create a write conflict, aborting the transaction
377+ User::where (['name ' => 'klinson ' ])->update (['age ' => 21 ]);
378+ }, 2 );
379+
380+ $ this ->fail ('Expected exception during transaction ' );
381+ } catch (BulkWriteException $ e ) {
382+ $ this ->assertInstanceOf (BulkWriteException::class, $ e );
383+ $ this ->assertStringContainsString ('WriteConflict ' , $ e ->getMessage ());
384+ }
367385
368386 $ this ->assertSame (2 , $ timesRun );
369387
0 commit comments