We have a multi-tenancy set up with one main and other tenant databases and having some problems running non-sqlite tests. Databases are mysql.
Currently trying to run tests against the main database and one tenant database. The connections in my model constructors are set like so:
BaseMainModel
$this->connection = config('database.main');
BaseTenantModel
$this->connection = config('database.tenant');
I observe the following:
Test are running fine with an sqlite in memory databse with the following settings in phpunit.xml:
<env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
<env name="APP_DEBUG" value="true"/>
<env name="DB_CONNECTION" value="testing"/>
<env name="DB_CONNECTION_TENANT" value="testing"/>
In config.database.connections
'testing' => [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
],
However, when running without the sqlite in memory database (so commenting out my two phpunit lines for <env name="DB_CONNECTION" value="testing"/> and <env name="DB_CONNECTION_TENANT" value="testing"/>) and running on my normal database, the tests start hanging after the first test.
So for example, if I have 5 tests in a file SomeTests.php, the first one completes, and the process hangs on the second one.
If I add the protected $connectionsToTransact = ['main', 'tenant']; to my TestCase class, even the first test doesn't complete.
Another thing to note is that I am overriding the refreshTestDatabase() method of the RefreshDatabase trait by creating my own trait and using laravel's trait. My trait looks like so:
trait RefreshDatabase
{
use BaseRefreshDatabase;
/**
* Refresh the in-memory database.
*
* @return void
*/
protected function refreshInMemoryDatabase()
{
$this->artisan('migrate');
$path = 'database' . DIRECTORY_SEPARATOR . 'migrations' . DIRECTORY_SEPARATOR . 'tenants';
Artisan::call('migrate', [
'--database' => 'testing',
'--path' => $path
]);
$this->app[Kernel::class]->setArtisan(null);
}
/**
* Refresh a conventional test database.
*
* @return void
*/
protected function refreshTestDatabase()
{
if (!RefreshDatabaseState::$migrated) {
$this->artisan('migrate:fresh');
$path = 'database' . DIRECTORY_SEPARATOR . 'migrations' . DIRECTORY_SEPARATOR . 'tenants';
$this->artisan('migrate:fresh', [
'--path' => $path,
'--database' => config('database.tenant')
]);
$this->app[Kernel::class]->setArtisan(null);
RefreshDatabaseState::$migrated = true;
}
$this->beginDatabaseTransaction();
}
}
I tried dumping in my test's setUp function:
class RelationsTest extends TestCase
{
use RefreshDatabase;
protected function setUp()
{
parent::setUp();
dump("here"); // this is logged
$this->product = factory(Product::class)->create();
dump("product created"); // this is not. However I dumped in the model constructors and it did enter the Product constructor
$this->someClass= factory(SomeClass::class)->create();
$this->user = factory(User::class)->create();
$this->otherClass = factory(OtherClass::class)->create();
$this->yetAnotherClass= factory(YetAnotherClass::class)->create([
'owner_id' => $this->user->id,
'product_id' => $this->product->id,
'someClass_id' => $this->someClass->id,
]);
}
...
Interestingly, if I run every test in the file separately, they run fine. So something happens in between the tests that I don't understand!
If I run two basic tests with just assertTrue(true) (not using factories or touching the database), they run fine.
Help is much appreciated! Thanks :)