instance(GraphClientInterface::class, new class implements GraphClientInterface { public function listPolicies(string $policyType, array $options = []): GraphResponse { return new GraphResponse(true, []); } public function getPolicy(string $policyType, string $policyId, array $options = []): GraphResponse { return new GraphResponse(true, []); } public function getOrganization(array $options = []): GraphResponse { return new GraphResponse(true, []); } public function applyPolicy(string $policyType, string $policyId, array $payload, array $options = []): GraphResponse { return new GraphResponse(true, []); } public function request(string $method, string $path, array $options = []): GraphResponse { return new GraphResponse( success: false, data: [], status: 400, errors: [ ['code' => 'BadRequest', 'message' => 'Bad request'], ], warnings: [], meta: [ 'error_code' => 'BadRequest', 'error_message' => 'Assignment list request failed', ], ); } public function getServicePrincipalPermissions(array $options = []): GraphResponse { return new GraphResponse(true, []); } }); $tenant = Tenant::factory()->create([ 'tenant_id' => 'tenant-assignment-fetch-failure', 'status' => 'active', ]); ensureDefaultProviderConnection($tenant); $policy = Policy::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'external_id' => 'policy-assignment-fetch-failure', 'policy_type' => 'settingsCatalogPolicy', 'platform' => 'windows', ]); $this->mock(PolicySnapshotService::class, function (MockInterface $mock) use ($policy): void { $mock->shouldReceive('fetch') ->once() ->andReturn([ 'payload' => [ '@odata.type' => '#microsoft.graph.deviceManagementConfigurationPolicy', 'id' => (string) $policy->external_id, 'name' => 'Policy snapshot', 'roleScopeTagIds' => ['0'], ], 'metadata' => [], 'warnings' => [], ]); }); $this->mock(ScopeTagResolver::class, function (MockInterface $mock) use ($tenant): void { $mock->shouldReceive('resolve') ->once() ->with(['0'], $tenant) ->andReturn([ ['id' => '0', 'displayName' => 'Default'], ]); }); $backupSet = app(BackupService::class)->createBackupSet( tenant: $tenant, policyIds: [(int) $policy->getKey()], actorEmail: 'assignment.fetch.failure@example.com', actorName: 'Assignment Fetch Failure', includeAssignments: true, includeScopeTags: true, ); $backupItem = $backupSet->items()->first(); expect($backupItem)->not->toBeNull(); expect($backupItem?->metadata['assignments_fetch_failed'] ?? false)->toBeTrue(); $assignmentFetchRun = OperationRun::query() ->where('tenant_id', (int) $tenant->getKey()) ->where('type', 'assignments.fetch') ->latest('id') ->first(); expect($assignmentFetchRun)->not->toBeNull(); expect($assignmentFetchRun?->status)->toBe('completed'); expect($assignmentFetchRun?->outcome)->toBe('failed'); expect($assignmentFetchRun?->summary_counts ?? [])->toMatchArray([ 'total' => 1, 'processed' => 0, 'failed' => 1, ]); expect($assignmentFetchRun?->failure_summary[0]['code'] ?? null)->toBe('assignments.fetch_failed'); expect(ProviderReasonCodes::isKnown((string) ($assignmentFetchRun?->failure_summary[0]['reason_code'] ?? '')))->toBeTrue(); });