mstdmstd's avatar

I got “There is no active transaction” error after I added RefreshDatabase into test file

Making in laravel 9.48.0 with mysql database http tests after I added RefreshDatabase into test file

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Foundation\Testing\Concerns\InteractsWithExceptionHandling;

use Tests\TestCase;
use App\Models\{Article, User};
use Illuminate\Support\Str;

class ArticlesCrudTest extends TestCase
{
    use InteractsWithExceptionHandling;
    use RefreshDatabase;

I got “There is no active transaction” error on 1st test from 15 tests in this file

I do not use sqllite, but other mysql database, so phpunit.xml have sqlite and memory options disabled:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
         bootstrap="vendor/autoload.php"
         colors="true"
         printerClass="Sempro\PHPUnitPrettyPrinter\PrettyPrinterForPhpUnit9"
>
    <testsuites>
        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>
    </testsuites>
    <coverage processUncoveredFiles="true">
        <include>
            <directory suffix=".php">./app</directory>
        </include>
    </coverage>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="BCRYPT_ROUNDS" value="4"/>
        <env name="CACHE_DRIVER" value="array"/>
        <!-- <env name="DB_CONNECTION" value="sqlite"/> -->
        <!-- <env name="DB_DATABASE" value=":memory:"/> -->
        <env name="MAIL_MAILER" value="array"/>
        <env name="QUEUE_CONNECTION" value="sync"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="TELESCOPE_ENABLED" value="false"/>
    </php>
</phpunit>

My control have code :

\Log::info( ' -1 store::');
DB::beginTransaction();
try {
    $article = Article::create([
        'title'        => $data['title'],
        'text'         => $data['text'],
        'text_shortly' => $data['text_shortly'],
        'creator_id'   => $data['creator_id'],
        'published'    => $data['published'],
    ]);
    \Log::info( ' -2 store::');
    DB::Commit();

    $article->load('creator');

    return response()->json(
        ['article' => (new ArticleResource($article))],
        HTTP_RESPONSE_OK_RESOURCE_CREATED
    ); // 201
} catch (\Exception $e) {
    DB::rollback();
}

In log file there are 2 lines from this controller. Before I added RefreshDatabase these tests worked ok, just like in real work.

I read some docs and not sure actually if RefreshDatabase works with mysql database ? –

What is wrong ?

Thanks!

0 likes
7 replies
lbecket's avatar

It looks like the issue is with using DB::beginTransaction() and DB::commit() in your controller code. When you use RefreshDatabase in your tests, the database is reset before each test, so any transactions that were started before the reset will not be active.

To resolve the error, you can either remove the transaction handling code from your controller or update your tests to handle transactions correctly. For example, wrap the relevant parts of the test in DB::beginTransaction() and DB::commit() to make sure the transaction is active during the test.

Note: RefreshDatabase is compatible with MySQL, so it is not the cause of the error.

1 like
mstdmstd's avatar

@lbecket 1) I dislike removing the transaction handling code from my controller. 2) as for “wrap the relevant parts of the test in DB::beginTransaction() and DB::commit() ” - not clear how it works? In this case seems in the controller I would have 2 opened transaction ? I suppose that : a) when test action started the database was reset and no active/opened transactions in this time? b) when test action started 1st transaction is opened - which I wrote in my control? That is NOT how it works ?

tykus's avatar

Try using the DatabaseMigrations trait for this particular Test case instead of RefreshDatabase trait.

Transactions can't be nested

2 likes
laracoft's avatar

@tykus

Thanks your answer helped me and should be the best model answer.

Sinnbeck's avatar

I tried setting up the same but it works fine. Maria db on the latest laravel.

Any chance you have xdebug? Then we can try comparing what happens

1 like
Sinnbeck's avatar

Btw. Doesnt really matter but might give you warnings in your IDE

The case of these are

DB::commit();
DB::rollBack();

Please or to participate in this conversation.