shouldReceive('expireOverduePurchases') ->once() ->ordered() ->andReturn(2); $carts = \Mockery::mock(ExpireCartReservationsService::class); $carts->shouldReceive('expireOverdue') ->once() ->ordered() ->andReturn(3); $logger = \Mockery::mock(LoggerInterface::class); Log::shouldReceive('channel') ->once() ->with('commands') ->andReturn($logger); $logger->shouldReceive('info') ->once() ->with('Stock reservation cleanup completed.', [ 'command' => 'reservations:expire', 'expired_purchases' => 2, 'expired_cart_items' => 3, 'total_expired' => 5, ]); $result = (new ExpireStockReservationsService($checkout, $carts))->expireOverdue(); $this->assertSame([ 'purchases' => 2, 'cart_items' => 3, ], $result); } public function test_it_logs_failed_cleanup_attempts_and_rethrows_the_error(): void { $exception = new RuntimeException('Unable to clean carts.'); $checkout = \Mockery::mock(CheckoutService::class); $checkout->shouldReceive('expireOverduePurchases')->once()->andReturn(2); $carts = \Mockery::mock(ExpireCartReservationsService::class); $carts->shouldReceive('expireOverdue')->once()->andThrow($exception); $logger = \Mockery::mock(LoggerInterface::class); Log::shouldReceive('channel') ->once() ->with('commands') ->andReturn($logger); $logger->shouldReceive('error') ->once() ->with('Stock reservation cleanup failed.', [ 'command' => 'reservations:expire', 'expired_purchases' => 2, 'expired_cart_items' => null, 'exception' => $exception, ]); $this->expectExceptionObject($exception); (new ExpireStockReservationsService($checkout, $carts))->expireOverdue(); } }