Learned today that using Storage::fake() only fakes the default disk… This might not be obvious at first, but it is definitely to be aware of.

Thanks to Jason McCreary from laravelshift.com.

Something else I stumbled on when refactoring Shift's logs to private app storage (storage/app/logs). I did so to remove the coupling between the application and the server. This is a pattern I've followed in the new side-projects, but had lived with this broken window in Shift.

However, testing this proved a bit of a challenge. I assumed Storage::fake() would fake all Storage calls. But it only fakes them for the default disk. In the case of Shift, I was now writing a log file to the local disk and then copying to the s3 disk.

To get the tests passing, I needed to fake both disks. Here's a full example test to ensure the log is sent to S3 even if a Shift fails.

#[Test]
public function it_stores_the_log_and_exit_code_on_error(): void
{
    $order = Order::factory()->create();

    Storage::fake('s3');
    Storage::fake('logs');

    $content = $this->faker()->md5();
    Storage::disk('logs')->put('shifts/' . $order->id . '.log', $content);

    Process::preventStrayProcesses()->fake(['php *' => 2]);

    try {
        PerformShift::dispatch($order);
    } catch (ShiftException) {
        $order->refresh();
        $this->assertSame(OrderStatus::Hold, $order->status);
        $this->assertSame(ExitCode::SystemError, $order->exit_code);
        $this->assertNull($order->pull_request_url);

        Storage::disk('s3')->assertExists('logs/' . $order->product->sku . '/' . $order->id . '.log', $content);
    }
}