testGeoipDir = storage_path('framework/testing/geoip-test-'.uniqid()); config([ 'geoip.database_path' => $this->testGeoipDir.'/GeoLite2-City.mmdb', // 테스트 시 retry 지연 최소화 (실제 운영은 config/geoip.php 기본값 사용) 'geoip.download.retry_attempts' => 1, 'geoip.download.retry_delay_ms' => 1, ]); if (File::isDirectory($this->testGeoipDir)) { File::deleteDirectory($this->testGeoipDir); } } protected function tearDown(): void { if (File::isDirectory($this->testGeoipDir)) { File::deleteDirectory($this->testGeoipDir); } Mockery::close(); parent::tearDown(); } /** * 서비스 인스턴스를 생성합니다 (ConfigRepository는 mock). */ private function makeService(?ConfigRepositoryInterface $configRepo = null): GeoIpDatabaseService { $configRepo ??= Mockery::mock(ConfigRepositoryInterface::class) ->shouldReceive('getCategory')->with('cache')->andReturn([])->byDefault() ->shouldReceive('saveCategory')->andReturn(true)->byDefault() ->getMock(); return new GeoIpDatabaseService($configRepo); } public function test_missing_license_key_returns_error(): void { config(['geoip.license_key' => '']); $service = $this->makeService(); $result = $service->updateDatabase(); $this->assertFalse($result['success']); $this->assertEquals('missing_license_key', $result['status']); } public function test_is_license_key_configured_reflects_config(): void { $service = $this->makeService(); config(['geoip.license_key' => '']); $this->assertFalse($service->isLicenseKeyConfigured()); config(['geoip.license_key' => 'abcd1234']); $this->assertTrue($service->isLicenseKeyConfigured()); } public function test_build_download_url_masks_license_key(): void { config(['geoip.license_key' => 'secretKey1234567890']); $service = $this->makeService(); $masked = $service->buildDownloadUrlForDisplay(true); $this->assertStringContainsString('secr', $masked); $this->assertStringNotContainsString('secretKey1234567890', $masked); $this->assertStringContainsString('****', $masked); } public function test_mask_key_keeps_first_four_chars(): void { $service = $this->makeService(); $this->assertEquals('abcd*****', $service->maskKey('abcd12345')); $this->assertEquals('****', $service->maskKey('abcd')); $this->assertEquals('**', $service->maskKey('ab')); } public function test_update_skipped_when_recently_updated_without_force(): void { config(['geoip.license_key' => 'abcd1234']); File::makeDirectory($this->testGeoipDir, 0755, true); $mmdbPath = $this->testGeoipDir.'/GeoLite2-City.mmdb'; File::put($mmdbPath, 'dummy-mmdb-content'); $service = $this->makeService(); $result = $service->updateDatabase(false); $this->assertTrue($result['success']); $this->assertEquals('skipped', $result['status']); $this->assertArrayHasKey('data', $result); } public function test_update_unauthorized_on_http_401(): void { config(['geoip.license_key' => 'invalid_key']); Http::fake([ 'download.maxmind.com/*' => Http::response('', 401), ]); $service = $this->makeService(); $result = $service->updateDatabase(true); $this->assertFalse($result['success']); $this->assertEquals('unauthorized', $result['status']); $this->assertStringContainsString('401', $result['message']); } public function test_update_download_failed_on_http_500(): void { config(['geoip.license_key' => 'validkey123']); Http::fake([ 'download.maxmind.com/*' => Http::response('', 500), ]); $service = $this->makeService(); $result = $service->updateDatabase(true); $this->assertFalse($result['success']); $this->assertEquals('download_failed', $result['status']); } public function test_get_database_status_returns_missing_when_file_absent(): void { $service = $this->makeService(); $status = $service->getDatabaseStatus(); $this->assertFalse($status['exists']); $this->assertEquals(0, $status['file_size_bytes']); $this->assertNull($status['last_updated_at']); } public function test_get_database_status_returns_metadata_when_file_exists(): void { File::makeDirectory($this->testGeoipDir, 0755, true); $mmdbPath = $this->testGeoipDir.'/GeoLite2-City.mmdb'; File::put($mmdbPath, str_repeat('x', 1024)); $service = $this->makeService(); $status = $service->getDatabaseStatus(); $this->assertTrue($status['exists']); $this->assertEquals(1024, $status['file_size_bytes']); $this->assertNotNull($status['last_updated_at']); } }