Remote Databases
If you have more than one Laravel codebase in your project, you might have issues when building databases and running your tests.
This might be because only one of the codebases knows how to build the database. Or perhaps multiple codebases interact with each other, and should all access the same database.
There are various reasons why you might have multiple codebases. For example:
- Your project uses a microservice architecture,
- You're implementing the Strangler Fig Pattern.
Building Databases Remotely
Adapt can build databases for other instances of Adapt.
This will be useful if you're running tests from one Laravel codebase, but the migrations and seeders to build the database exist in another.
- Install Adapt into both codebases.
- In the codebase that runs the tests, set the
remote_build_url
config setting. Or you can specify it per-test by adding the$remoteBuildUrl
property to your test-classes. The url just needs to point to somewhere within the other codebase's routing. - When each test runs, Adapt sends an http request to the remote instance. Adapt on the other side picks up the request automatically.
- The remote instance then builds the database (for its connection with the same name).
- It returns the details back to the first codebase, which then uses the database and continues the test, like normal.
If a database built like this can be reused, Adapt will skip the http request next time and just re-use it straight away.
⚙️ See configuration
# .env.testing
ADAPT_REMOTE_BUILD_URL=https://…
or
<?php
// config/code_distortion.adapt.php
return [
…
'remote_build_url' => env('ADAPT_REMOTE_BUILD_URL', 'https://…'), // or null
…
];
or
<?php
// tests/Feature/MyFeatureTest.php
use CodeDistortion\Adapt\AdaptDatabase;
use Tests\TestCase;
class MyFeatureTest extends TestCase
{
use AdaptDatabase;
protected ?string $remoteBuildUrl = 'https://…'; // or null
…
}
These are the settings that are passed from your tests to the remote instance:
- config
project_name
- config
build_sources.initial_imports
, or test-class property$initialImports
- config
build_sources.migrations
, or test-class property$migrations
- config
build_sources.seeders
, or test-class property$seeders
- test-class property
$isBrowserTest
, or when a browser test is automatically detected- config
reuse_methods.transactions
, or test-class property$transactions
- config
reuse_methods.journals
, or test-class property$journals
- config
reuse_methods.snapshots
, or test-class property$snapshots
- config
scenarios
- config
verify_databases
NOTE
It's best to have the same version of Adapt installed in both places. Adapt will throw an exception if the versions aren't compatible.
It's also best to have the same database connections set up in each config/database.php
file.
TIP
Multiple databases can be built for a test using this method. Just use the ->remoteBuildUrl('https://…')
method when building extra databases.
Sharing Databases Remotely
Adapt can share databases that have been prepared (locally, or remotely as above) with other Laravel codebases.
If your project makes http requests to a second local Laravel project (e.g. when calling an API), you'd probably want it to connect a database that was prepared for the test.
Adapt gives you a header to add to these requests, which contains details about the database.
If more than one database is built for a test, they'll all be included inside the same header.
- Install Adapt into both codebases.
- Add the header to your http requests (example below).
- When receiving the request, Adapt on the other side will automatically detect these headers. It then swaps to the "testing" environment, and uses the test database/s for the duration of the request.
<?php
// somewhere.php
use CodeDistortion\Adapt\AdaptDatabase;
$adaptHeaders = trait_exists(AdaptDatabase::class)
? AdaptDatabase::getShareConnectionsHeaders()
: [];
// [
// 'adapt-remote-share' => 'eyJkdG9WZXJzaW9uIjo2LCJzaGFyYWJsZUNvbmZpZ1BhdGgiOm51bGwsImNvbm5lY3Rpb25EQnMiOnsibXlzcWwiOiJkYl9mZjYzNGJfNzZmYmZhZjE1OTU1In19',
// ]
$response = Http::withOptions(['headers' => $adaptHeaders])->post($url, $data);
NOTE
Checking first that the AdaptDatabase
trait exists (see above) means that the code won't break in non-local or testing environments (where Adapt wouldn't be installed).
If you'd like the header key to be included in the value, pass true
to AdaptDatabase::getShareConnectionsHeaders(true)
:
<?php
// somewhere.php
use CodeDistortion\Adapt\AdaptDatabase;
$adaptHeaders = trait_exists(AdaptDatabase::class)
? AdaptDatabase::getShareConnectionsHeaders(true)
: [];
// [
// 'adapt-remote-share' => 'adapt-remote-share: eyJkdG9WZXJzaW9uIjo2LCJzaGFyYWJsZUNvbmZpZ1BhdGgiOm51bGwsImNvbm5lY3Rpb25EQnMiOnsibXlzcWwiOiJkYl9mZjYzNGJfNzZmYmZhZjE1OTU1In19',
// ]
NOTE
It's best to have the same version of Adapt installed in both places. Adapt will throw an exception if the versions aren't compatible.
It's also best to have the same database connections set up in each config/database.php
file.
WARNING
You will most likely want to turn transaction-reuse off when sharing databases like this, as any changes you make from one connection won't be seen by the other.
You can turn this off by updating Adapt's reuse_methods.transactions
config setting, or by adding the $transactions
property to your test-classes.