Testing
GeoIp is designed for easy testing. Use the null driver to prevent any external API calls in your test suite.
Null Driver
Set the driver to null in your test environment:
Option 1: phpunit.xml
<env name="GEOIP_DRIVER" value="null"/>Option 2: TestCase setup
protected function getEnvironmentSetUp($app)
{
$app['config']->set('geo-ip.driver', 'null');
}The null driver returns an IpData with only the ip field populated. All other fields are null, and isResolved() returns false.
Switching Drivers in phpunit.xml
You can override any driver from your phpunit.xml using environment variables:
<!-- Use the null driver (no external calls) -->
<env name="GEOIP_DRIVER" value="null"/>
<!-- Use ip-api for integration tests -->
<env name="GEOIP_DRIVER" value="ip-api"/>
<!-- Use ipinfo with a test token -->
<env name="GEOIP_DRIVER" value="ipinfo"/>
<env name="IPINFO_TOKEN" value="test-token-here"/>
<!-- Use DB-IP Lite with a test database -->
<env name="GEOIP_DRIVER" value="dbip"/>
<env name="DBIP_DB_PATH" value="tests/fixtures/dbip-city-lite.mmdb"/>
<!-- Use MaxMind with a test database -->
<env name="GEOIP_DRIVER" value="maxmind"/>
<env name="MAXMIND_DB_PATH" value="tests/fixtures/GeoLite2-City-Test.mmdb"/>
<!-- Disable caching during tests -->
<env name="GEOIP_CACHE_ENABLED" value="false"/>A typical phpunit.xml setup for testing:
<phpunit>
<php>
<env name="GEOIP_DRIVER" value="null"/>
<env name="GEOIP_CACHE_ENABLED" value="false"/>
</php>
</phpunit>Switching Drivers at Runtime
Use the driver() method to swap drivers within a test — for example, to compare results from a local database against a remote API:
use ArielMejiaDev\GeoIp\GeoIp;
it('resolves a Cincinnati IP similarly with dbip and ip-api', function () {
$geoip = app(GeoIp::class);
$dbip = $geoip->driver('dbip')->lookup('129.137.1.1');
$ipApi = $geoip->driver('ip-api')->lookup('129.137.1.1');
expect($dbip->countryCode)->toBe('US')
->and($ipApi->countryCode)->toBe('US');
expect($dbip->city)->toBe('Cincinnati')
->and($ipApi->city)->toBe('Cincinnati');
});See Runtime Driver for a full example.
Faking Specific Data
When your tests need specific geolocation data, bind a fake driver:
use ArielMejiaDev\GeoIp\Contracts\Driver;
use ArielMejiaDev\GeoIp\GeoIp;
use ArielMejiaDev\GeoIp\IpData;
it('shows domestic pricing for US visitors', function () {
$fakeDriver = new class implements Driver {
public function lookup(string $ip): IpData
{
return new IpData(
ip: $ip,
countryCode: 'US',
country: 'United States',
city: 'New York',
);
}
};
$this->app->singleton(GeoIp::class, fn () => new GeoIp(driver: $fakeDriver));
$response = $this->get('/pricing');
$response->assertSee('Domestic pricing');
});Testing with IpAddress Directly
For unit tests that don't need the full service container, create IpAddress instances directly:
use ArielMejiaDev\GeoIp\IpAddress;
use ArielMejiaDev\GeoIp\IpData;
$ip = new IpAddress('8.8.8.8', new IpData(
ip: '8.8.8.8',
countryCode: 'US',
country: 'United States',
));
expect($ip->is('US'))->toBeTrue();
expect($ip->country())->toBe('United States');Testing Conditionals
it('applies LATAM pricing for Mexican visitors', function () {
$ip = new IpAddress('1.2.3.4', new IpData(
ip: '1.2.3.4',
countryCode: 'MX',
country: 'Mexico',
));
$applied = false;
$ip->whenIn(['MX', 'CO', 'AR'], function () use (&$applied) {
$applied = true;
});
expect($applied)->toBeTrue();
});Testing Macros
it('checks custom macro', function () {
IpAddress::macro('isNorthAmerican', function () {
return $this->isIn(['US', 'CA', 'MX']);
});
$ip = new IpAddress('8.8.8.8', new IpData(ip: '8.8.8.8', countryCode: 'US'));
expect($ip->isNorthAmerican())->toBeTrue();
IpAddress::flushMacros();
});