setAccessible(true); try { $method->invoke($service, 'content', 'image/png', 'test.png'); } catch (\Exception $e) { // Exception is expected since the key is fake, but it should try Gemini $this->assertTrue( str_contains($e->getMessage(), 'Gemini') || str_contains($e->getMessage(), 'communication avec l\'API') || str_contains($e->getMessage(), 'La clé API Gemini') ); } // 2. Test Vertex AI JSON Credentials string $fakeCreds = json_encode([ 'type' => 'service_account', 'project_id' => 'my-vertex-project', ]); Config::set('services.gemini.key', $fakeCreds); $serviceVertex = new GeminiService(); try { $method->invoke($serviceVertex, 'content', 'image/png', 'test.png'); } catch (\Exception $e) { // Exception expected during auth token exchange, but it must be a Vertex error $this->assertStringContainsString('Vertex', $e->getMessage()); } } /** * Test MistralService features. */ public function test_mistral_service() { Config::set('services.mistral.key', 'fake-mistral-key'); $mistral = new \App\Services\MistralService(); $method = new ReflectionMethod(\App\Services\MistralService::class, 'analyzeContent'); $method->setAccessible(true); // PDF should be rejected $this->expectException(\Exception::class); $this->expectExceptionMessage('ne prend en charge que les images'); $method->invoke($mistral, 'content', 'application/pdf', 'test.pdf'); } }