DatabaseTransactionsTest.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <?php
  2. namespace Illuminate\Tests\Database;
  3. use Exception;
  4. use Illuminate\Database\Capsule\Manager as DB;
  5. use Illuminate\Database\DatabaseTransactionsManager;
  6. use Mockery as m;
  7. use PHPUnit\Framework\TestCase;
  8. use Throwable;
  9. class DatabaseTransactionsTest extends TestCase
  10. {
  11. /**
  12. * Setup the database schema.
  13. *
  14. * @return void
  15. */
  16. protected function setUp(): void
  17. {
  18. $db = new DB;
  19. $db->addConnection([
  20. 'driver' => 'sqlite',
  21. 'database' => ':memory:',
  22. ]);
  23. $db->addConnection([
  24. 'driver' => 'sqlite',
  25. 'database' => ':memory:',
  26. ], 'second_connection');
  27. $db->setAsGlobal();
  28. $this->createSchema();
  29. }
  30. protected function createSchema()
  31. {
  32. foreach (['default', 'second_connection'] as $connection) {
  33. $this->schema($connection)->create('users', function ($table) {
  34. $table->increments('id');
  35. $table->string('name')->nullable();
  36. $table->string('value')->nullable();
  37. });
  38. }
  39. }
  40. /**
  41. * Tear down the database schema.
  42. *
  43. * @return void
  44. */
  45. protected function tearDown(): void
  46. {
  47. foreach (['default', 'second_connection'] as $connection) {
  48. $this->schema($connection)->drop('users');
  49. }
  50. m::close();
  51. }
  52. public function testTransactionIsRecordedAndCommitted()
  53. {
  54. $transactionManager = m::mock(new DatabaseTransactionsManager);
  55. $transactionManager->shouldReceive('begin')->once()->with('default', 1);
  56. $transactionManager->shouldReceive('commit')->once()->with('default');
  57. $this->connection()->setTransactionManager($transactionManager);
  58. $this->connection()->table('users')->insert([
  59. 'name' => 'zain', 'value' => 1,
  60. ]);
  61. $this->connection()->transaction(function () {
  62. $this->connection()->table('users')->where(['name' => 'zain'])->update([
  63. 'value' => 2,
  64. ]);
  65. });
  66. }
  67. public function testTransactionIsRecordedAndCommittedUsingTheSeparateMethods()
  68. {
  69. $transactionManager = m::mock(new DatabaseTransactionsManager);
  70. $transactionManager->shouldReceive('begin')->once()->with('default', 1);
  71. $transactionManager->shouldReceive('commit')->once()->with('default');
  72. $this->connection()->setTransactionManager($transactionManager);
  73. $this->connection()->table('users')->insert([
  74. 'name' => 'zain', 'value' => 1,
  75. ]);
  76. $this->connection()->beginTransaction();
  77. $this->connection()->table('users')->where(['name' => 'zain'])->update([
  78. 'value' => 2,
  79. ]);
  80. $this->connection()->commit();
  81. }
  82. public function testNestedTransactionIsRecordedAndCommitted()
  83. {
  84. $transactionManager = m::mock(new DatabaseTransactionsManager);
  85. $transactionManager->shouldReceive('begin')->once()->with('default', 1);
  86. $transactionManager->shouldReceive('begin')->once()->with('default', 2);
  87. $transactionManager->shouldReceive('commit')->once()->with('default');
  88. $this->connection()->setTransactionManager($transactionManager);
  89. $this->connection()->table('users')->insert([
  90. 'name' => 'zain', 'value' => 1,
  91. ]);
  92. $this->connection()->transaction(function () {
  93. $this->connection()->table('users')->where(['name' => 'zain'])->update([
  94. 'value' => 2,
  95. ]);
  96. $this->connection()->transaction(function () {
  97. $this->connection()->table('users')->where(['name' => 'zain'])->update([
  98. 'value' => 2,
  99. ]);
  100. });
  101. });
  102. }
  103. public function testNestedTransactionIsRecordeForDifferentConnectionsdAndCommitted()
  104. {
  105. $transactionManager = m::mock(new DatabaseTransactionsManager);
  106. $transactionManager->shouldReceive('begin')->once()->with('default', 1);
  107. $transactionManager->shouldReceive('begin')->once()->with('second_connection', 1);
  108. $transactionManager->shouldReceive('begin')->once()->with('second_connection', 2);
  109. $transactionManager->shouldReceive('commit')->once()->with('default');
  110. $transactionManager->shouldReceive('commit')->once()->with('second_connection');
  111. $this->connection()->setTransactionManager($transactionManager);
  112. $this->connection('second_connection')->setTransactionManager($transactionManager);
  113. $this->connection()->table('users')->insert([
  114. 'name' => 'zain', 'value' => 1,
  115. ]);
  116. $this->connection()->transaction(function () {
  117. $this->connection()->table('users')->where(['name' => 'zain'])->update([
  118. 'value' => 2,
  119. ]);
  120. $this->connection('second_connection')->transaction(function () {
  121. $this->connection('second_connection')->table('users')->where(['name' => 'zain'])->update([
  122. 'value' => 2,
  123. ]);
  124. $this->connection('second_connection')->transaction(function () {
  125. $this->connection('second_connection')->table('users')->where(['name' => 'zain'])->update([
  126. 'value' => 2,
  127. ]);
  128. });
  129. });
  130. });
  131. }
  132. public function testTransactionIsRolledBack()
  133. {
  134. $transactionManager = m::mock(new DatabaseTransactionsManager);
  135. $transactionManager->shouldReceive('begin')->once()->with('default', 1);
  136. $transactionManager->shouldReceive('rollback')->once()->with('default', 0);
  137. $transactionManager->shouldNotReceive('commit');
  138. $this->connection()->setTransactionManager($transactionManager);
  139. $this->connection()->table('users')->insert([
  140. 'name' => 'zain', 'value' => 1,
  141. ]);
  142. try {
  143. $this->connection()->transaction(function () {
  144. $this->connection()->table('users')->where(['name' => 'zain'])->update([
  145. 'value' => 2,
  146. ]);
  147. throw new Exception;
  148. });
  149. } catch (Throwable $e) {
  150. }
  151. }
  152. public function testTransactionIsRolledBackUsingSeparateMethods()
  153. {
  154. $transactionManager = m::mock(new DatabaseTransactionsManager);
  155. $transactionManager->shouldReceive('begin')->once()->with('default', 1);
  156. $transactionManager->shouldReceive('rollback')->once()->with('default', 0);
  157. $transactionManager->shouldNotReceive('commit');
  158. $this->connection()->setTransactionManager($transactionManager);
  159. $this->connection()->table('users')->insert([
  160. 'name' => 'zain', 'value' => 1,
  161. ]);
  162. $this->connection()->beginTransaction();
  163. $this->connection()->table('users')->where(['name' => 'zain'])->update([
  164. 'value' => 2,
  165. ]);
  166. $this->connection()->rollBack();
  167. }
  168. public function testNestedTransactionsAreRolledBack()
  169. {
  170. $transactionManager = m::mock(new DatabaseTransactionsManager);
  171. $transactionManager->shouldReceive('begin')->once()->with('default', 1);
  172. $transactionManager->shouldReceive('begin')->once()->with('default', 2);
  173. $transactionManager->shouldReceive('rollback')->once()->with('default', 1);
  174. $transactionManager->shouldReceive('rollback')->once()->with('default', 0);
  175. $transactionManager->shouldNotReceive('commit');
  176. $this->connection()->setTransactionManager($transactionManager);
  177. $this->connection()->table('users')->insert([
  178. 'name' => 'zain', 'value' => 1,
  179. ]);
  180. try {
  181. $this->connection()->transaction(function () {
  182. $this->connection()->table('users')->where(['name' => 'zain'])->update([
  183. 'value' => 2,
  184. ]);
  185. $this->connection()->transaction(function () {
  186. $this->connection()->table('users')->where(['name' => 'zain'])->update([
  187. 'value' => 2,
  188. ]);
  189. throw new Exception;
  190. });
  191. });
  192. } catch (Throwable $e) {
  193. }
  194. }
  195. /**
  196. * Get a schema builder instance.
  197. *
  198. * @return \Illuminate\Database\Schema\Builder
  199. */
  200. protected function schema($connection = 'default')
  201. {
  202. return $this->connection($connection)->getSchemaBuilder();
  203. }
  204. public function connection($name = 'default')
  205. {
  206. return DB::connection($name);
  207. }
  208. }