每次测试后,Laravel测试都不会回滚事务

时间:2018-02-10 20:04:49

标签: laravel testing pdo transactions mariadb

我的测试在开始测试之前使用特征RefreshDatabase来“迁移新鲜”,并为每种测试方法使用事务。

迁移工作正常,但交易根本不起作用。

我尝试公开我的设置:

  • 在Docker容器中运行的MariaDB 10.1(我已经证明我的测试中使用的所有表都在InnoDB中,因此支持事务)
  • 基础测试类使用RefreshDatabase
  • 我尝试了一个单独的连接,与$connectionsToTransact一起进行测试,并使用默认连接进行测试。交易不起作用

我的setUp方法:

protected function setUp()
{
    parent::setUp();

    Queue::fake();
}

您可以在此Gist中找到完整的Test Class和Test基类: https://gist.github.com/patriziotomato/e25de1e160dace08edefa682b64bd150

我已经尝试调试了,并且也开始使用PDO启动和回滚事务,所以看起来laravel代码尝试进行事务处理和回滚,但它在我的测试中没有任何影响。

我需要一些其他可能出错的想法

5 个答案:

答案 0 :(得分:2)

您可能正在使用Model::truncate()

不幸的是,自MySQL 5.1.32起,truncate()与事务“不兼容”。您可以删除表,但不能在事务内truncate()

http://dev.mysql.com/doc/refman/5.1/en/truncate-table.html

根据此URL,从MySQL 5.1.32开始,TRUNCATE TABLE为DDL, 不像DELETE这样的DML。这意味着TRUNCATE TABLE将导致 事务块中间的隐式COMMIT。因此,使用DELETE 在表上的FROM,您需要清空而不是TRUNCATE TABLE。

StackOverflow和Laracasts的相关答案:

答案 1 :(得分:1)

要回滚在您的测试文件中进行的交易,您可以使用DatabaseTransactions

...
use Illuminate\Foundation\Testing\DatabaseTransactions;
...

class SomeTest extends TestCase {

    use DatabaseTransactions;

public some_assertion_method()
{
    ...
}

答案 2 :(得分:1)

我有同样的问题。从来没有找到确切的原因,但有一个解决方法 - 手动启动和回滚事务:

public function setUp()
{
    parent::setUp();
    DB::beginTransaction();
}

public function tearDown()
{
    DB::rollback();
    parent::tearDown();
}

答案 3 :(得分:0)

我自己有一个类似的MySQL设置问题。我还从上面尝试了Anthony的解决方案,并且也看到了相同的...1305 SAVEPOINT trans2 does not exist...错误。

在我的案例中,罪魁祸首是代码中的Model::truncate()操作(用于重新导入命令)。某种程度上,这似乎使Laravel的事务/回滚处理(或MySQL的?)感到不安,从而导致上述错误。使用Model::all()->each->delete()可以解决我的问题。 (经过一些进一步的测试,看来我也无法重置auto_increment值,所以这是问题所在。)

  

值得注意的是,它可能不会在内存数据库中发生,而在MySQL设置中发生,例如,如果流氓条目保持完整,很容易与即将到来的测试混在一起,从而导致难以调试的错误,所以请小心...:)

更新 最佳答案on this Laracast thread实际上说明事务操作在操作期间具有隐式提交,并在测试期间引发事务堆栈。

答案 4 :(得分:-2)

更改文件phpunit.xml

<php>
        <env name="DB_CONNECTION" value="mysq"/>
        <env name="APP_ENV" value="local"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
        <env name="MAIL_DRIVER" value="array"/>
        <env name="SMS_DRIVER" value="array"/>
</php>

将此特征添加到测试文件中:

use DatabaseTransactions;