Logo

dev-resources.site

for different kinds of informations.

Testing Temporary URLs in Laravel Storage

Published at
1/12/2025
Categories
laravel
testing
php
aws
Author
tegos
Categories
4 categories in total
laravel
open
testing
open
php
open
aws
open
Author
5 person written this
tegos
open
Testing Temporary URLs in Laravel Storage

How to Test Laravel's Storage::temporaryUrl()

Laravel provides a powerful and flexible Storage facade for file storage and manipulation. One notable feature is temporaryUrl(), which generates temporary URLs for files stored on services like Amazon S3 or DigitalOcean Spaces. However, Laravel's documentation does not cover how to test this method effectively. Testing it can pose challenges, particularly when using Storage::fake, as the fake storage driver does not support temporaryUrl() and throws the error:

This driver does not support creating temporary URLs.

In this article, we’ll demonstrate two approaches to testing Storage::temporaryUrl() using a practical example. These approaches involve mocking the filesystem and using fake storage. Both methods ensure your tests remain isolated and reliable.

Example Setup

We’ll use a PriceExport model, a corresponding controller, and test cases to illustrate the testing process. Here’s the setup:

Model

final class PriceExport extends Model
{
    protected $fillable = [
        'user_id',
        'supplier_id',
        'path',
        'is_auto',
        'is_ready',
        'is_send',
    ];

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    public function supplier(): BelongsTo
    {
        return $this->belongsTo(Supplier::class);
    }
}
Enter fullscreen mode Exit fullscreen mode

Controller

The controller generates a temporary URL for the file using the temporaryUrl method:

final class PriceExportController extends Controller
{
    /**
     * @throws ItemNotFoundException
     */
    public function download(PriceExport $priceExport): DownloadFileResource
    {
        if (!$priceExport->is_ready || empty($priceExport->path)) {
            throw new ItemNotFoundException('price export');
        }

        $fileName = basename($priceExport->path);
        $diskS3 = Storage::disk(StorageDiskName::DO_S3->value);

        $url = $diskS3->temporaryUrl($priceExport->path, Carbon::now()->addHour());

        $downloadFileDTO = new DownloadFileDTO($url, $fileName);

        return DownloadFileResource::make($downloadFileDTO);
    }
}
Enter fullscreen mode Exit fullscreen mode

Testing temporaryUrl()

Test Case 1: Using Storage::fake

While Storage::fake doesn’t natively support temporaryUrl, we can mock the fake storage to simulate the method’s behavior. This approach ensures you can test without needing a real storage service.

final class PriceExportTest extends TestCase
{
    public function test_price_export_download_fake(): void
    {
        // Arrange
        $user = $this->getDefaultUser();
        $this->actingAsFrontendUser($user);

        $supplier = SupplierFactory::new()->create();
        $priceExport = PriceExportFactory::new()->for($user)->for($supplier)->create([
            'path' => 'price-export/price-2025.xlsx',
        ]);

        $expectedUrl = 'https://temporary-url.com/supplier-price-export-2025.xlsx';
        $expectedFileName = basename($priceExport->path);

        $fakeFilesystem = Storage::fake(StorageDiskName::DO_S3->value);

        // Mock the fake filesystem
        $proxyMockedFakeFilesystem = Mockery::mock($fakeFilesystem);
        $proxyMockedFakeFilesystem->shouldReceive('temporaryUrl')->andReturn($expectedUrl);
        Storage::set(StorageDiskName::DO_S3->value, $proxyMockedFakeFilesystem);

        // Act
        $response = $this->postJson(route('api-v2:price-export.price-exports.download', $priceExport));

        // Assert
        $response->assertOk()->assertJson([
            'data' => [
                'name' => $expectedFileName,
                'url' => $expectedUrl,
            ]
        ]);
    }
}
Enter fullscreen mode Exit fullscreen mode

Test Case 2: Using Storage::shouldReceive

This method leverages Laravel’s built-in mocking capabilities to mock the temporaryUrl behavior directly.

final class PriceExportTest extends TestCase
{
    public function test_price_export_download_mock(): void
    {
        // Arrange
        $user = $this->getDefaultUser();
        $this->actingAsFrontendUser($user);

        $supplier = SupplierFactory::new()->create();
        $priceExport = PriceExportFactory::new()->for($user)->for($supplier)->create([
            'path' => 'price-export/price-2025.xlsx',
        ]);

        $expectedUrl = 'https://temporary-url.com/supplier-price-export-2025.xlsx';
        $expectedFileName = basename($priceExport->path);

        // Mock the storage behavior
        Storage::shouldReceive('disk')->with(StorageDiskName::DO_S3->value)->andReturnSelf();
        Storage::shouldReceive('temporaryUrl')->andReturn($expectedUrl);

        // Act
        $response = $this->postJson(route('api-v2:price-export.price-exports.download', $priceExport));

        // Assert
        $response->assertOk()->assertJson([
            'data' => [
                'name' => $expectedFileName,
                'url' => $expectedUrl,
            ]
        ]);
    }
}
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  1. Storage::fake Limitation: The fake storage driver does not support temporaryUrl. Use a mocked version of the fake storage to work around this.
  2. Mocking Storage: Laravel’s Storage::shouldReceive simplifies mocking methods like temporaryUrl when testing controllers.
  3. Isolation: Both approaches ensure your tests don’t depend on external services, maintaining fast and reliable tests.

By combining these techniques, you can effectively test Storage::temporaryUrl() and ensure your application’s functionality is well-verified.

testing Article's
30 articles in total
Favicon
Top 10 Online Postman-Like Tools for API Testing and Development
Favicon
What Is POS Testing? A Step-by-Step Breakdown for Retail Success
Favicon
Maximize the efficiency of your tests with TAST
Favicon
Building a String Calculator with Test-Driven Development (TDD): A Step-by-Step Guide
Favicon
Building a new Chat
Favicon
Testing with JWT in .NET APIs
Favicon
Why Duplicating Environments for Microservices Backfires
Favicon
From Legacy to Modern: Creating Self-Testable APIs for Seamless Integration
Favicon
Research Paper Series: Using Lightweight Formal Methods to Validate a Key-Value Storage Node in Amazon S3
Favicon
End-to-End API Testing: How Mocking and Debugging Work Together
Favicon
Testing Temporary URLs in Laravel Storage
Favicon
The Role of AI in Cybersecurity: Opportunities and Challenges
Favicon
AI Software Testing: Revolutionizing Quality Assurance
Favicon
Testing with different text
Favicon
Need someone to contribute in writing test code for my open source project
Favicon
Finding the coverables
Favicon
5 Reasons Businesses Should Give Priority to Performance Testing
Favicon
5 Things to Know About Workday AI Testing
Favicon
Before TDD: Why you need to know what Mocks, Stubs, and Spies are?
Favicon
Software Testing Tasks with Challenges, Tools, and Best Practices
Favicon
Comprehensive Guide to Waits in Selenium 4
Favicon
Test Case Vs Test Scenario
Favicon
Introducing Codin: A CLI for Automated ML Model Testing in CI/CD
Favicon
Your Roadmap to Mastering k6 for Performance Testing
Favicon
Setting values in R6 classes, and testing with shiny::MockShinySession
Favicon
Introducing BlockBuster: is my asyncio event loop blocked?
Favicon
Wednesday Links - Edition 2025-01-08
Favicon
How to Connect External Speakers to Your Xbox Console
Favicon
Testing Pi Logic integrations.
Favicon
Capturing and Testing Logs in Java with SLF4J and Logback: A Simple Guide

Featured ones: