I'm using an SQLite connection and doctrine migrations for functional testing with PHPUnit.
I'm making a DB migration from scratch in the setUp
method:
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');
}
and then I can write/read from DB. E.g.:
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());
}
and it works. And it does work even when I call twice the service with the same arguments. In this case it only has to write the first time:
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());
}
The problem comes when I have to test two calls that have to write both:
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());
}
Here comes the error:
- XXX::test_add_two_different_events_should_add_two_event Doctrine\DBAL\Exception\ReadOnlyException: An exception occurred while executing 'INSERT INTO xxx (xxx, xxx, xxx, xxx) VALUES (?, ?, ?, ?)' with params [xxx, "xxx", "xxx", "xxx"]:
SQLSTATE[HY000]: General error: 8 attempt to write a readonly database
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
I've tried changing the DB file permissions between calls, but nothing changes:
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());
}
Any idea of where could the error come from? Every service call will call persist
+ flush
in this case.
getTotal()
call synchronises things? If so (big "if"), it might be that both updates are trying to run at the same time. Does anything change if you add$this->assertEquals(1, $response->getTotal());
after the firstexecute()
? – Frowardexecute
call.getTotal
is just a getter. I even tried callingsleep
for some seconds between calls, so they're not trying to update at the same time neither. BTW, if I callexecute
only once, it works. This is the weird part – Toscaniniresponse->getTotal()
waits for the first service to complete before returning. If it's not too difficult, I'd try with the extra call (essentially duplicate the four lines in your first test, but change the 2nd assert to 2). – Frowardvar_dump
outputs "root". root user has full permissions – Toscanini$yourConnection->setAttribute(PDO:: PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES)
based on this example and this PR – Commanding$this->setAttribute(PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES, true);
but I get this error: Fatal error: Undefined class constant 'SQLITE_ATTR_EXTENDED_RESULT_CODES' – Toscanini