ensureRun( tenant: $tenant, type: 'test.release', inputs: ['foo' => 'bar'], initiator: $user, ); $job = new class($operationRun) implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public function __construct(public OperationRun $operationRun) { $this->withFakeQueueInteractions(); } }; $middleware = new TrackOperationRun; $middleware->handle($job, function ($job): void { $job->release(60); }); $operationRun->refresh(); expect($operationRun->status)->toBe('running'); expect($operationRun->outcome)->toBe('pending'); }); it('marks an operation run failed when the wrapped job throws inside middleware execution', function () { [$user, $tenant] = createUserWithTenant(role: 'owner'); /** @var OperationRunService $operationRunService */ $operationRunService = app(OperationRunService::class); $operationRun = $operationRunService->ensureRun( tenant: $tenant, type: 'test.exception', inputs: ['foo' => 'bar'], initiator: $user, ); $job = new class($operationRun) implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public function __construct(public OperationRun $operationRun) { $this->withFakeQueueInteractions(); } }; $middleware = new TrackOperationRun; expect(fn () => $middleware->handle($job, function (): void { throw new RuntimeException('wrapped job failure'); }))->toThrow(RuntimeException::class); $operationRun->refresh(); expect($operationRun->status)->toBe('completed') ->and($operationRun->outcome)->toBe('failed') ->and(data_get($operationRun->failure_summary, '0.code'))->toBe('exception.unhandled'); });