Repository navigation
Testing
Geolocator::fake() swaps the facade root for an in-memory fake, so lookups never touch a database:
use SameOldNick\Geolocator\Drivers\Fake\FakeGeolocator;
use SameOldNick\Geolocator\DTOs\AsnResult;
use SameOldNick\Geolocator\DTOs\LocationResult;
use SameOldNick\Geolocator\Facades\Geolocator;
/** @var FakeGeolocator $driver */
$driver = Geolocator::fake();
Geolocator::lookup('8.8.8.8'); // generated result, no database access
$result = new LocationResult(
ipAddress: '8.8.8.8',
country: null,
city: null,
asn: AsnResult::create(15169, 'Google LLC'),
);
// An exact address takes precedence over a glob, which takes precedence over the wildcard.
$driver->mock('8.8.8.8', $result); // one address
$driver->mock('8.8.8.*', $result); // any address matching the pattern
$driver->mock('1.1.1.1'); // null: this address resolves to nothing
$driver->mock('*', $result); // anything elsemock() returns the fake so it can be chained, and the same results can be passed to fake() up front:
$driver = Geolocator::fake(
mockedResults: [
'8.8.8.8' => $result,
'1.1.1.1' => null,
],
chanceOfEmpty: 0,
);A mocked value is a LocationResult, a closure, or null for an empty result. A closure receives the address and the name of the method that was called, so one mock can answer the edition-specific lookups differently:
$driver->mock('8.8.*', fn (string $ip, string $method) => $method === 'lookupAsn'
? new LocationResult(
ipAddress: $ip,
country: null,
city: null,
asn: AsnResult::create(15169, 'Google LLC'),
)
: null);Addresses you have not mocked get generated data, except private, reserved and malformed addresses, which resolve to an empty result. A mock overrides that: a '*' wildcard answers private addresses too, so reach for it deliberately.
chanceOfEmpty is the percentage chance of an empty result for an unmocked public address. It defaults
to 0, which keeps tests deterministic, and it is passed by name:
Geolocator::fake(chanceOfEmpty: 100);The fake stays installed for the rest of the test, which is usually what you want since every test gets a fresh container. To hand the facade back to the configured driver mid-test, swap its real root back in:
Geolocator::swap(app(\SameOldNick\Geolocator\GeolocatorManager::class));The fake above replaces the geolocator. To exercise the real ip-location-db driver instead, replace the reader it opens:
-
SameOldNick\Geolocator\Drivers\Fake\FakeReaderimplements the sameContracts\Readerinterface as the real reader, returns generated records, and supportsmock()with the same glob and wildcard matching rules as the fake geolocator. - The driver resolves each edition's reader from a
Contracts\ReaderProvider. The shipped providers extendAbstractReaderProvider, so binding one of them to a subclass that returns aFakeReaderis the seam to replace.
A mocked lookup never opens a .mmdb file, so nothing in the suite proves the driver reads a real database correctly. Keep at least one lookup against a real database — in a staging environment, or in a test gated on the file being present.