SQLite SQLSTATE[HY000]:一般错误:8 尝试写入只读数据库

Man*_*olo 6 php sqlite phpunit doctrine doctrine-migrations

我正在使用 SQLite 连接和学说迁移对 PHPUnit 进行功能测试。我在setUp方法中从头开始进行数据库迁移:

public function setUp()
{
    parent::setUp();
    
    @unlink(__DIR__ . '/../../../../../../../var/sqlite.db');

    exec('./vendor/bin/doctrine-migrations migrations:migrate --db-configuration=migrations-db-test.php --configuration=migrations_test.yml --no-interaction');
}
Run Code Online (Sandbox Code Playgroud)

然后我可以从数据库写入/读取。例如:

public function test_add_event_should_add_event()
{
    $service = $this->getAdEventComparativesUpdateService();
    $request = AdEventComparativesUpdateServiceRequest::make(self::AD_ID, self::USER_IP);
    $response = $service->execute($request);

    $this->assertEquals(1, $response->getTotal());
}
Run Code Online (Sandbox Code Playgroud)

它有效。即使我使用相同的参数调用两次服务,它也确实有效。在这种情况下,它只需要在第一次写入:

public function test_add_two_same_events_should_add_one_event()
{
    $service = $this->getAdEventComparativesUpdateService();
    $request = AdEventComparativesUpdateServiceRequest::make(self::AD_ID, self::USER_IP);
    // Call twice
    $service->execute($request);
    $response = $service->execute($request);

    $this->assertEquals(1, $response->getTotal());
}
Run Code Online (Sandbox Code Playgroud)

当我必须测试两个必须同时编写的调用时,问题就出现了:

public function test_add_two_different_events_should_add_two_events()
{
    $service = $this->getAdEventComparativesUpdateService();
    $request = AdEventComparativesUpdateServiceRequest::make(self::AD_ID, self::USER_IP);
    $response = $service->execute($request);

    $service = $this->getAdEventComparativesUpdateService();
    $request = AdEventComparativesUpdateServiceRequest::make(self::AD_ID, self::OTHER_USER_IP);
    $response = $service->execute($request); // **** It fails here

    $this->assertEquals(2, $response->getTotal());
}
Run Code Online (Sandbox Code Playgroud)

错误来了:

  1. XXX::test_add_two_different_events_should_add_two_event Doctrine\DBAL\Exception\ReadOnlyException: 执行带有参数 [xxx, "xxx", 'INSERT INTO xxx (xxx, xxx, xxx, xxx) VALUES (?, ?, ?, ?)' 时发生异常"xxx", "xxx"]:

SQLSTATE[HY000]:一般错误:8 尝试写入只读数据库

xxx/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLiteDriver.php:78 xxx/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php:128 xxx/vendor/doctrine/dbal/lib/ Doctrine/DBAL/Statement.php:178 xxx/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php:281 xxx/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php: 1014 xxx/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:378 xxx/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:356 xxx/vendor/doctrine/orm/lib/Doctrine /ORM/EntityManager.php:235 xxx/DoctrineSession.php:32 xxx/TransactionalApplicationService.php:39 xxx/xxx/test.php:100

我尝试在调用之间更改 DB 文件权限,但没有任何更改:

public function test_add_two_different_events_should_add_two_event()
{
    $service = $this->getAdEventComparativesUpdateService();
    $request = AdEventComparativesUpdateServiceRequest::make(self::AD_ID, self::USER_IP);
    $response = $service->execute($request);

    chmod(__DIR__ . '/../../../../../../../var', 0777);
    chmod(__DIR__ . '/../../../../../../../var/sqlite.db', 0777);
    chown(__DIR__ . '/../../../../../../../var', 'www-data');
    chgrp(__DIR__ . '/../../../../../../../var', 'www-data');
    chown(__DIR__ . '/../../../../../../../var/sqlite.db', 'www-data');
    chgrp(__DIR__ . '/../../../../../../../var/sqlite.db', 'www-data');
   //die;
   // Here I checked the /var sqlite.db permissions. They are 0777

    $service = $this->getAdEventComparativesUpdateService();
    $request = AdEventComparativesUpdateServiceRequest::make(self::AD_ID, self::OTHER_USER_IP);
    $response = $service->execute($request);

    $this->assertEquals(2, $response->getTotal());
}
Run Code Online (Sandbox Code Playgroud)

知道错误来自哪里吗?在这种情况下,每个服务调用都会调用persist+ flush

wp7*_*8de 0

很难回答这个问题,因为我们没有真正的[mre]。最常见的是,这是一个权限问题,但看起来您已经探索过这条路线。我想我有预感这里发生了什么:

\n

看起来单元测试在每次测试时都会重新创建数据库,即取消链接数据库文件,然后当打开连接时,如果不存在\xe2\x80\x99t ,则会自动创建数据库文件。因此,在两次写入尝试的情况下,连接首先打开并保持打开状态。然后,同一或另一个测试调用数据库文件取消链接,并且后续写入命令失败。

\n