SQLite SQLSTATE [HY000]:常规错误:8次尝试写入只读数据库

时间:2020-07-31 09:57:00

标签: php sqlite doctrine phpunit 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');
}

然后我就可以从数据库进行写/读了。例如:

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());
}

,并且有效。即使我使用相同的参数两次调用该服务,它也能正常工作。在这种情况下,只需写一次即可:

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());
}

当我必须测试必须同时写两个的两个呼叫时,问题就来了:

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());
}

出现错误:

  1. XXX :: test_add_two_different_events_should_add_two_event Doctrine \ DBAL \ Exception \ ReadOnlyException:执行带有参数[xxx,“ xxx”,“ xxx”,的'INSERT INTO xxx(xxx,xxx,xxx,xxx)VALUES(?,?,?,?)'时发生异常“ 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

我尝试更改两次调用之间的数据库文件权限,但没有任何变化:

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());
}

关于错误可能从何而来的任何想法?在这种情况下,每个服务呼叫都会呼叫persist + flush

1 个答案:

答案 0 :(得分:0)

很难回答这个问题,因为我们没有真正的[mre]。最常见的是这是一个权限问题,但是您似乎已经探索过此路线。我想我直觉这是怎么回事:

单元测试似乎在每次测试时都会重新创建数据库,即取消链接数据库文件,然后在打开连接时自动创建数据库文件(如果该文件不存在)。因此,在两次写入尝试的情况下,连接首先打开并保持打开状态。然后,数据库文件取消链接被相同或另一个测试调用,随后的写入命令失败。